zoukankan      html  css  js  c++  java
  • Delphi调用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;
    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
  • 相关阅读:
    Dump 文件生成与分析
    打造支持apk下载和html5缓存的 IIS(配合一个超简单的android APP使用)具体解释
    GridView编辑删除操作
    google域名邮箱申请 gmail域名邮箱申请(企业应用套件)指南
    nvl,空时的推断和取值
    如何将图片保存至自定义分组
    Java实现 蓝桥杯VIP 算法训练 集合运算
    Java实现 蓝桥杯VIP 算法训练 瓷砖铺放
    Java实现 蓝桥杯VIP 算法训练 瓷砖铺放
    Java实现 蓝桥杯VIP 算法训练 集合运算
  • 原文地址:https://www.cnblogs.com/key-ok/p/3358944.html
Copyright © 2011-2022 走看看