请问能把DLL中的一个类导出吗?然后在另一个delphi应用程序中使用该类创建对象。

jixiaoqiang 2007-12-01 11:58:43
unit demo;

interface
uses StrUtils,Dialogs;
type
TYD=class(TObject)
public
x1:Integer;
procedure aa();
function aa1():String;

private
m1:Integer;
procedure bb();

published
constructor Create();
end;

implementation
constructor TYD.Create();
begin
//
end;
procedure TYD.aa();
begin
ShowMessage('xxx');
end;
function TYD.aa1():String;
begin
result:='100';
end;
procedure TYD.bb();
begin
//
end;
end.

上面的类如何让他导出? 导出之后在另一程序中如何使用该类?? 高手指点指点!!
...全文
79 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
jixiaoqiang 2007-12-02
  • 打赏
  • 举报
回复
总体来说,很晕。
上面有两处代码打错了,但是纠正之后运行仍然报内存错,就是不知道怎么调用对象里的东西的。.....
1.dll的project1中多了var x,yd
2.'Project1.dll.dll'; 多.dll
jixiaoqiang 2007-12-02
  • 打赏
  • 举报
回复
看了半天资料,整到这个地步整不下去了,运行报内存错误:

大家看看错在哪里???
一、dll代码:
library Project1;

uses
ComServ,
demo in 'demo.pas',
demo_Intf in 'demo_Intf.pas';

var
x:Integer;
yd:TYD;
exports
DllGetClassObject,
DllCanUnloadNow,
DllRegisterServer,
DllUnregisterServer,init;
{$R *.RES}

begin
end.

--------------------------------------------------------------------------
unit demo_Intf;

interface
type
TYDBase=class(TObject)
public
x1:Integer;
procedure aa();virtual;abstract;
function aa1():String;virtual;abstract;

private
m1:Integer;

end;
implementation

end.
------------------------------------------------------------------------------------
unit demo;

interface
uses StrUtils,Dialogs,demo_Intf;
type
TYD=class(TYDBase)
public
x1:Integer;
procedure aa();override;
function aa1():String;override;

private
m1:Integer;

published
constructor Create();
end;

function init():TYD;stdcall;

implementation
constructor TYD.Create();
begin
//
end;
procedure TYD.aa();
begin
ShowMessage('xxx');
end;
function TYD.aa1():String;
begin
result:='100';
end;
function init():TYD;
begin
result:=TYD.Create;
end;
end.



二、调用工程代码
procedure TForm1.Button1Click(Sender: TObject);
var
dllHandle: THandle;
yd:TYDBase;
begin
yd:=Init;
yd.aa;
{
dllHandle := LoadLibrary('Project1.DLL'); //动态载入DLL,并返回其句柄
try
if dllHandle <> 0 then //如果载入成功则获取SplitString函数的地址
yd:= GetProcAddress(dllHandle, 'yd');
if not (@yd = nil) then
begin
yd.aa;
//ShowMessage(PChar(yd1.aa1));
//yd1.x1:=70;
//ShowMessage(IntToStr(yd1.x1));
end;
finally
FreeLibrary(dllHandle); //调用完毕收回DLL占用的资源
end;
}
end;
-----------------------------------------------------------------------
unit demo_Intf;

interface
type
TYDBase=class(TObject)
public
x1:Integer;
procedure aa();virtual;abstract;
function aa1():String;virtual;abstract;

private
m1:Integer;

end;
function Init:TYDBase;external 'Project1.dll.dll';

implementation

end.

liangpei2008 2007-12-02
  • 打赏
  • 举报
回复
不知道说的对不对,不对请指教~
---------------------------------------------
Dll中封装对象一般是这样的
1.Dll中的对象实例只能在dll中创建
2.应用程序只能调用动态绑定的方法
3.对于Dll中对象的释放
对于为什么只能调用动态方法,很明显,不把方法声明为虚方法,对象的方法就进不去VMT表,VMT中就不会有方法的入口地址,否则,应用程序即使得到了对象的地址,也得不到相应的方法。
所以一般大家都用抽象类或接口来实现DLL对类的封装。
如果用接口的话,可以利用实例计数器来自动管理对象的生命期,从而达到对象释放的目的。

我在项目中创建了一个ObjectBroker的COM+,用COM+来调用DLL
liangpei2008 2007-12-02
  • 打赏
  • 举报
回复
同意楼上,用Interface实现
1.创建COM+及接口函数
2.调用对象时用COM+的接口函数调用Dll
comanche 2007-12-02
  • 打赏
  • 举报
回复
说明一下为什么不可以, 类函数在 dll 中的位置是相对的,只有在 load 进入后才确定一个绝对位置
dll & exe 都引用了 demo_intf, RTTI是存在于 dll 和 exe 中的, 分别独立, exe里并不知道 TYDBase这个类在dll 中的派生类存在, 多态就不能被使用, 换句话说这时你不能由dll建立由exe愁释放,入口是不同的,必须由建立一一方完成释放才行,这样只有 interface 才能实现了, 不用interface的代码就是当时能用,也不能保证之后的运行是稳定的
comanche 2007-12-02
  • 打赏
  • 举报
回复
dll用使用对像是不可以的,但可以使用接口

定义一个接口文件
Ia = interface
{guid ctrl+shift+c}
procedure xxx; stdcall;
end;

dll 和调用者都引用这个接口文件

dll中大概如下

TA = class(TInterfacedObject, Ia)
protected
{ Ia}
procedrue xxx; stdcall; 实现这个
end;

function exportA: Ia; stdcall;
begin
result := TA.Crate as Ia;
end;

调用者这边不要释放 Ia,由记数去完成

你的代码的想法是没错的 demo_Intf 中定义的是抽像类, interface 实质上就是一个抽像类. 这里改改应该就可以了

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧