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.上面的类如何让他导出? 导出之后在另一程序中如何使用该类?? 高手指点指点!!
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.上面的类如何让他导出? 导出之后在另一程序中如何使用该类?? 高手指点指点!!
解决方案 »
- 常量与变量的连接
- Delphi7中怎么实现像极品时刻表那样的Combox
- 来者有分------飞鹰论坛Delphi版真诚的邀请各路英豪加盟!!
- FR做的报表中:打印时,单击windows桌面的右下角图标弹出......
- 一个循环在进行中,怎样点击一个按钮终止它?
- Access2000总提示输入密码!烦!!!
- 请问各位哪里能申请中文的免费网页空间,50分谢谢。
- 怎么样才能让button控件显示hint?
- 我用DBGRID新增一条记录因重复键不能保存,而当我取消时,如何将DBGRID中新增的那行去掉?cancel没反应,delete又会将我调出修改的记录取消时删掉.
- 老千,你还在吗?我又有一个问题……
- 创建的窗体不能显示!!那里错了!?
- 用DBGridEh下面的footer如何实现脚注,如合计,网格内的数据记录等等.
一、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;
implementationend.
------------------------------------------------------------------------------------
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';implementationend.
上面有两处代码打错了,但是纠正之后运行仍然报内存错,就是不知道怎么调用对象里的东西的。.....
1.dll的project1中多了var x,yd
2.'Project1.dll.dll'; 多.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 实质上就是一个抽像类. 这里改改应该就可以了
dll & exe 都引用了 demo_intf, RTTI是存在于 dll 和 exe 中的, 分别独立, exe里并不知道 TYDBase这个类在dll 中的派生类存在, 多态就不能被使用, 换句话说这时你不能由dll建立由exe愁释放,入口是不同的,必须由建立一一方完成释放才行,这样只有 interface 才能实现了, 不用interface的代码就是当时能用,也不能保证之后的运行是稳定的
1.创建COM+及接口函数
2.调用对象时用COM+的接口函数调用Dll
---------------------------------------------
Dll中封装对象一般是这样的
1.Dll中的对象实例只能在dll中创建
2.应用程序只能调用动态绑定的方法
3.对于Dll中对象的释放
对于为什么只能调用动态方法,很明显,不把方法声明为虚方法,对象的方法就进不去VMT表,VMT中就不会有方法的入口地址,否则,应用程序即使得到了对象的地址,也得不到相应的方法。
所以一般大家都用抽象类或接口来实现DLL对类的封装。
如果用接口的话,可以利用实例计数器来自动管理对象的生命期,从而达到对象释放的目的。我在项目中创建了一个ObjectBroker的COM+,用COM+来调用DLL