Delphi调用DLL中的接口

 

最近很少上论坛,这几次发现好几个问题都是围绕如何使用DLL中的接口而展开的。

问题描述:

具体问题就是在隐式使用接口变量后,在FreeLibrary执行后,就会出现一个非法访址的错误。

这个错误的原因就是在FreeLibrary后,DLL以的代码均为不可用状态,而在代码执行完整个过程后,VCL要对RTL类型的数据进行清理。而在清理过程中肯定要对接口进行减1并进行释放相关对象。而对象代码已从进程空间卸载,故报非法访址错误!

解决方法:

所以要想解决该问题,就应该把DLL调用过程放到一个单独的过程中,其目的就是让调用完毕后,让VCL来清理接口。清理完毕后返回后,再调用FreeLibrary来从进程空间中卸载DLL。

错误调用代码为:

 

var libHandle: THandle; GetDllObject: TGetDllObject; ADllObj: ICustomDLL; begin libHandle := LoadLibrary(PChar(ExtractFilePath(ParamStr(0)) + edtDLLFileName.Text)); try if (libHandle = 0) then raise Exception.Create('载入DLL失败!'); @GetDllObject := GetProcAddress(libHandle, 'GetDllObject'); if (@GetDllObject <> nil) then begin ADllObj := GetDllObject() AS ICustomDLL; //GetDllObject() ADllObj.OwnerAppHandle := Application.Handle; edtDLLName.Text := ADllObj.DLLName; ADllObj.Execute; end else RaiseLastOSError(); finally FreeLibrary(libHandle); //***前面正常,到这里就报错*** end; end;

正确的全过程为:

 

//DLL部分 1.接口定义 unit DLLInf; interface type ITest = interface ['{623008B1-5E8C-463C-9048-821C14FB20C1}'] function ShowMSG(ParamStr:Widestring):Widestring; end; implementation end. 2.接口实现 unit DLLImpl; interface uses DLLInf ; type TTest=class(TinterfacedObject,ITest) public function ShowMSG(ParamStr:Widestring):Widestring; end; implementation function TTest.ShowMSG(ParamStr: Widestring): Widestring; begin result:=result+ ParamStr; end; end. 3.导出类单元 function TestObj:ITest;stdcall; begin result := TTest.create; end; exports TestObj;

//前端调用 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,DLLInf; type TTestObj=function:ITest;stdcall; TForm1 = class(TForm) btn1: TButton; edt1: TEdit; procedure btn1Click(Sender: TObject); private { Private declarations } TestObj: TTestObj; myDLLHandle: THandle; procedure getDLLObject; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.getDLLObject; var testStr:Widestring; begin testStr:='Test String'; @TestObj:= GetProcAddress(myDLLHandle, 'TestObj'); if @TestObj<>nil then TestObj.ShowMSG(testStr) //调用DLL中的对象并执行相关方法 else Application.MessageBox('在Dll动态链接库中加载方法失败!','提示',mb_ok); end; procedure TForm1.btn1Click(Sender: TObject); begin myDLLHandle:=loadlibrary('DLLDemo.dll'); try if myDLLHandle>0 then getDLLObject; finally FreeLibrary(myDLLHandle); End ; end; end.

 

你可能感兴趣的:(Delphi开发/调用DLL)