• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Delphi调用DLL中的接口

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

问题描述:

具体问题就是在隐式使用接口变量后,在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;
View Code

正确的全过程为:

//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;
View Code
//前端调用
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.
View Code

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
matlab 基础发布时间:2022-07-18
下一篇:
Matlab按图片分割数据为训练集和测试集并生成label发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap