创建一抽象类然后,在DLL中对该类进行定义.通过调用DLL得到类,然后在应用程序中创建实例.但是一旦释放实例后,或者调用freelibrary后就会报错.
代码如下:
<1>抽象类的单元:
unit XPerson;interface
uses
Classes;
type
TPersonClass=Class of IPerson;
IPerson=Class
protected
Function GetName:String;Virtual;Abstract;
Procedure SetName(Const Value:String);Virtual;Abstract;
Public
Constructor Create(Const Value:String);Virtual;
Property Name:String Read GetName Write SetName; end;
implementation{ IPerson }constructor IPerson.Create(const Value: String);
begin
inherited Create;
Self.Name:=Value;
end;end.
<2>DLL代码:
library 代码:library Person;uses
SysUtils,
Classes,
UPerson in 'UPerson.pas',
XPerson in '..\XPerson.pas';{$R *.res}
function PersonClass:TPersonClass;Stdcall;
begin
Result:=TPerson;
end;
Exports
PersonClass;
begin
end.
DLL中定义抽象类单元代码:
unit UPerson;interface
uses
XPerson;
type
TPerson=Class(IPerson)
private
Fname:String;
Protected
function GetName:String;Override;
Procedure SetName(Const Value:String);Override;
Public
Property Name:String Read GetName Write SetName;
Destructor Destroy;Override;
end;
implementation{ TPerson }destructor TPerson.Destroy;
begin inherited;
end;function TPerson.GetName: String;
begin
Result:=Fname;
end;procedure TPerson.SetName(Const Value:String);
begin
FName:=Value;
end;end.
<3>应用程序的代码:
var
Form1: TForm1;
DLLHandle:THandle;
PersonClass:Function:TPersonClass;StdCall;
APerson:IPerson;
implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
DLLHandle:=LoadLibrary('E:\projects\Person.dll');
try
if DLLHandle=0 then
Exit;
@PersonClass:=GetProcAddress(DLLHandle,'PersonClass');
if @PersonClass<>nil then
begin
APerson:=PerSonClass.Create('Michael');
Edit1.Text:=APerson.Name;
end;
Finally
Aperson.Free;
end;
end;
还忘高手不吝赐教,到底是怎么回事,怎样释放才不能出错.
代码如下:
<1>抽象类的单元:
unit XPerson;interface
uses
Classes;
type
TPersonClass=Class of IPerson;
IPerson=Class
protected
Function GetName:String;Virtual;Abstract;
Procedure SetName(Const Value:String);Virtual;Abstract;
Public
Constructor Create(Const Value:String);Virtual;
Property Name:String Read GetName Write SetName; end;
implementation{ IPerson }constructor IPerson.Create(const Value: String);
begin
inherited Create;
Self.Name:=Value;
end;end.
<2>DLL代码:
library 代码:library Person;uses
SysUtils,
Classes,
UPerson in 'UPerson.pas',
XPerson in '..\XPerson.pas';{$R *.res}
function PersonClass:TPersonClass;Stdcall;
begin
Result:=TPerson;
end;
Exports
PersonClass;
begin
end.
DLL中定义抽象类单元代码:
unit UPerson;interface
uses
XPerson;
type
TPerson=Class(IPerson)
private
Fname:String;
Protected
function GetName:String;Override;
Procedure SetName(Const Value:String);Override;
Public
Property Name:String Read GetName Write SetName;
Destructor Destroy;Override;
end;
implementation{ TPerson }destructor TPerson.Destroy;
begin inherited;
end;function TPerson.GetName: String;
begin
Result:=Fname;
end;procedure TPerson.SetName(Const Value:String);
begin
FName:=Value;
end;end.
<3>应用程序的代码:
var
Form1: TForm1;
DLLHandle:THandle;
PersonClass:Function:TPersonClass;StdCall;
APerson:IPerson;
implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
DLLHandle:=LoadLibrary('E:\projects\Person.dll');
try
if DLLHandle=0 then
Exit;
@PersonClass:=GetProcAddress(DLLHandle,'PersonClass');
if @PersonClass<>nil then
begin
APerson:=PerSonClass.Create('Michael');
Edit1.Text:=APerson.Name;
end;
Finally
Aperson.Free;
end;
end;
还忘高手不吝赐教,到底是怎么回事,怎样释放才不能出错.
解决方案 »
- 请问高手,如何判断idftp(indy)是否正在进行下载?
- 严重鄙视买日本货的人!
- 你能解决吗?马上送分!Fatal Error
- dbgrid的问题,谢谢
- 如何在delphi中读取word文档!!!!
- activeform(网页)上可以声明全局变量吗?如何取得数据表中某一列的最大值?谢谢!
- 如何利用delphi2010的rtti获得某对象属性的属性?
- 这样查找网上邻居上的共享资源错了吗?
- TNMFTP编程下载时出现:socket send aborted,高分请教--在线等待
- D7+SQL2005+win7显示小数点后面的小数位数问题?
- 关于ThemeEngine中的TeComboBox的中文显示问题?
- 一个关于如何获取当前记录的记录号的问题,请高手赐教!
报错:
project project1.exe raised exception class EinvalidPointer with message 'invalid pointer operation'.
如果FreeLibrary(dllhandle);
报错:
Access violation at address 00403E1C in module 'project1.exe'.read of address 00ED0B10.
如果引用了DLL,在引用者和DLL的Project Source中引用ShareMem,并且放在第一行。library Person;uses
ShareMem,
SysUtils,
Classes,
UPerson in 'UPerson.pas',
XPerson in '..\XPerson.pas';
另外,建议你DLL传指针,虽然类实际也是指针,我觉得好像不容易出错。
http://blog.csdn.net/lead001/archive/2005/07/06/415890.aspx
应该这样的思路:
1.在dll导出创建和释放接口函数,
2.在接口函数中创建和释放对象,
3.由exe来调用接口创建和释放对象,
exe调用创建接口获取dll创建的对象指针,
然后就可以使用了(当然在exe中要有抽象类定义)
TPersonClass=Class of IPerson;
IPerson=Class
protected
Function GetName:String;Virtual;Abstract;
Procedure SetName(Const Value:String);Virtual;Abstract;
Public
Constructor Create(Const Value:String);Virtual;
Property Name:String Read GetName Write SetName; end;
抽象类中应该全部是抽象的.把
Constructor Create(Const Value:String);Virtual;
Property Name:String Read GetName Write SetName;
去掉..
不要希望创建成一个抽象类的实例
外部程序一定要创建的话, 直接继承一个不就行了.
而应该在DLL里释放.再写一个导出过程, 用来释放和类的实例吧.
在调用模块的USE模块里加ShareMem注意一定要是第一个
我的外部程序是引用了抽象类单元,dll也是如此,对抽象类的定义放在DLL中,所以可以用DLL传出类.这样外部程序就可以调用,这仅仅是我做的试验.这样的做法没有什么不对的.
在外部程序不能释放,那么怎样在DLL中释放呢?
还请高手给出代码,谢谢!
TPersonClass=Class
protected
Function GetName:String;Virtual;Abstract;
Procedure SetName(Const Value:String);Virtual;Abstract;
Public
Property Name:String Read GetName Write SetName;
end;
// 虚拟类声明
// 如果是虚拟类, 就不要声明任何非虚拟过程或函数. type
TPerson=Class(TPersonClass)
private
Fname:String;
Protected
function GetName:String;Override;
Procedure SetName(Const Value:String);Override;
Public
Property Name:String Read GetName Write SetName;
end;function PersonClass(const Value: String): TPersonClass;Stdcall;
procedure FreeClass(APreson: TPersonClass); stdcall;implementation// 返回的要实例, 而不是类.
// 如果是类的话, 你用到的永远是虚拟的类
// 在此处你犯了个错觉误
function PersonClass(const Value: String): TPersonClass;
begin
Result := TPerson.Create;
Result.Name := Value;
end;
// 销毁
procedure FreeClass(APreson: TPersonClass);
begin
APreson.Free;
end;{ TPerson }
function TPerson.GetName: String;
begin
Result:=Fname;
end;procedure TPerson.SetName(Const Value:String);
begin
FName:=Value;
end;// 要用静态方法引用
// 因为取得的是类的实例, 如果过早的释放DLL, 会使实例无法引用
function PersonClass(const Value: String): TPersonClass;Stdcall; external 'Person.dll';
procedure FreeClass(APreson: TPersonClass); stdcall; external 'Person.dll';//以下是我人测试代码
var
aa: TPersonClass;procedure TForm1.FormCreate(Sender: TObject);
begin
aa := PersonClass('eeeeeeee');
end;procedure TForm1.Button1Click(Sender: TObject);
begin
showmessage(aa.Name);
end;procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
FreeClass(aa);
end;
procedure FreeClass(APreson: TPersonClass); stdcall;
为什么要返回抽象类的实例.
我已经这么做了,但是还是报错!!
project project1.exe raised exception class EinvalidPointer with message 'invalid pointer operation'.
project project1.exe raised exception class EinvalidPointer with message 'invalid pointer operation'.
即使引用sharemem单元,在退出外部程序的时候还是报同样的错误.
但是发送消息释放就OK了.
why?????????????????????
还请高手指教.................................
偶用的是delphi7library testDLL;uses
//sharemem,
SysUtils,
Classes,
Utest in 'Utest.pas',
XPerson in '..\XPerson.pas';{$R *.res}
Function CreatePerson(Value:String ):IPerson;StdCall
begin
Result:=TPerson.Create;
Result.Name:=Value;
end;
Procedure FreePerson(var Aperson:IPerson);StdCall;
begin
Aperson.Free;
end;Exports
CreatePerson,FreePerson;
begin
end.
//---------//
unit Utest;interface
uses
sharemem,XPerson;
type
Tperson=Class(IPerson)
Private
FName:String;
Protected
Function GetName:String;Override;
Procedure SetName(Const Value:String);Override;
Public
Property Name:String Read GetName Write SetName;
end;implementation{ Tperson }function Tperson.GetName: String;
begin
Result:=Fname;
end;procedure Tperson.SetName(const Value: String);
begin
FName:=Value;
end;end.
//---------------------//
unit XPerson;interface
uses
Classes;
type IPerson=Class
protected
Function GetName:String;Virtual;Abstract;
Procedure SetName(Const Value:String);Virtual;Abstract;
Public Property Name:String Read GetName Write SetName;
end;implementationend.
//---------------外部程序代码//
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,XPerson;
const
WM_FreePerson=WM_User+1;
type
TForm1 = class(TForm)
Label1: TLabel;
edtname: TEdit;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
Procedure WMFreePerson(var Msg:TMessage);Message WM_FreePerson;
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
DLLHandle:THandle;
Aperson:Iperson;
CreatePerson:Function(value:String):IPerson;StdCall;
FreePerson:Procedure(var value:IPerson);StdCall;
implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
DLLHandle:=Loadlibrary('E:\projects\delphi\测试DLL\DLL\testDLL.dll');
if DLLHandle<>0 then
begin
@CreatePerson:=GetProcAddress(DLlHandle,'CreatePerson');
if @CreatePerson<>nil then
begin
Aperson:=CreatePerson('Michael');
edtName.text:=Aperson.Name;
//Button2Click(Self);
postMessage(handle,WM_FreePerson,0,0);
//发送消息释放不能引用sharemem单元,否则报错
end;
end;
end;procedure TForm1.Button2Click(Sender: TObject);
begin
if APerson<>nil then exit;
@FreePerson:=GetProcAddress(DLlHandle,'FreePerson');
if @FreePerson<>nil then
FreePerson(Aperson);
end;procedure TForm1.WMFreePerson(var Msg: TMessage);
begin
Button2Click(Self);
end;end.