问题描述:

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

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

解决方法:

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

错误调用代码为:

var
libHandle: THandle;
GetDllObject: TGetDllObject;
ADllObj: ICustomDLL;
begin
libHandle := LoadLibrary(PChar(ExtractFilePath(ParamStr()) + edtDLLFileName.Text));
try
if (libHandle = ) 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部分
.接口定义
unit DLLInf;
interface
type
ITest = interface
['{623008B1-5E8C-463C-9048-821C14FB20C1}'] function ShowMSG(ParamStr:Widestring):Widestring;
end;
implementation
end.
.接口实现
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.
.导出类单元
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> then
getDLLObject;
finally
FreeLibrary(myDLLHandle);
End ;
end;
end.

Delphi调用DLL中的接口的更多相关文章

  1. AutoCAD.NET 不使用P/Invoke方式调用acad.exe或accore.dll中的接口(如acedCommand、acedPostCommand等)

    使用C#进行AutoCAD二次开发,有时候由于C#接口不够完善,或者低版本AutoCAD中的接口缺少,有些工作不能直接通过C#接口来实现,所以需要通过P/Invoke的方式调用AutoCAD的其他DL ...

  2. Qt调用dll中的功能函数

    声明: 事先我已经自己动手写了一个简单的dll文件(myDLL.dll),C版接口的.并且用我前两篇有关DLL文章里面的方法,从dll中导出了导入库(.lib)文件,dll中有两个函数,原型如下:   ...

  3. 在VS2012中采用C++中调用DLL中的函数 (4)

    这两天因为需要用到VS2012来生成一个DLL代码,但是之前并没有用过DLL相关的内容,从昨天开始尝试调试DLL的文件调用,起初笔者在网络上找到了3片采用VSXXX版本进行调试的例子,相关的内容见本人 ...

  4. 在C++中调用DLL中的函数 (3)

    1.dll的优点 代码复用是提高软件开发效率的重要途径.一般而言,只要某部分代码具有通用性,就可将它构造成相对独立的功能模块并在之后的项目中重复使用.比较常见的例子是各种应用程序框架,ATL.MFC等 ...

  5. 在C++中调用DLL中的函数 (2)

    应用程序使用DLL可以采用两种方式: 一种是隐式链接,另一种是显式链接.在使用DLL之前首先要知道DLL中函数的结构信息. Visual C++6.0在VC\bin目录下提供了一个名为Dumpbin. ...

  6. 在C++中调用DLL中的函数

    如何在C++中调用DLL中的函数 应用程序使用DLL可以采用两种方式:一种是隐式链接,另一种是显式链接.在使用DLL之前首先要知道DLL中函数的结构信息.Visual C++6.0在VC\bin目录下 ...

  7. 纯静态界面中(html)中通过js调用dll中的方法从数据库中读取数据

    最近接到一个离职员工的任务,一个搭好框架的ERP系统,看了两天,说一下看到的东西,整个项目目录中我没发现一个.aspx后缀的文件,全是静态HTML文件,之后发现他用的jquery简直看的头疼,不过大概 ...

  8. 【原创】在VS2012中采用C++中调用DLL中的函数(4)

    这两天因为需要用到VS2012来生成一个DLL代码,但是之前并没有用过DLL相关的内容,从昨天开始尝试调试DLL的文件调用,起初笔者在网络上找到了3片采用VSXXX版本进行调试的例子,相关的内容见本人 ...

  9. 在C++中调用DLL中的函数(3)

    1.dll的优点 代码复用是提高软件开发效率的重要途径.一般而言,只要某部分代码具有通用性,就可将它构造成相对独立的功能模块并在之后的项目中重复使用.比较常见的例子是各种应用程序框架,ATL.MFC等 ...

随机推荐

  1. SSL/TLS Server supports TLSv1.0

    远程登录服务器后打开注册表编辑器,点开HKEY-LOCAL-MACHINE,SYSTEM,CURRENTCONTROLSET下的Control 找到SecurityProviders下的SCHANNE ...

  2. [LeetCode&Python] Problem 387. First Unique Character in a String

    Given a string, find the first non-repeating character in it and return it's index. If it doesn't ex ...

  3. 田螺便利店——联想笔记本进入不了BIOS的解决方法

    当计算机遇到问题时,很多情况下需要进入BIOS进行解决.但很多新出的联想笔记本电脑在开机时,无论怎么疯狂的按F2,Fn+F2,F12或者Del,都无法进入BIOS,十分气人.       这种现象出现 ...

  4. Codeforces Round #516(Div 2)

    比赛链接:传送门 A. Make a triangle!(简单思维) 题目大意: 给你三条边,问你最多加多少长度能使这三条边能构成三角形. 思路: 最大边小于答案加另外两条边的和. #include ...

  5. java-内部类访问特点-私有成员内部类-静态成员内部类-局部内部类访问局部变量

    1.内部类访问特点: - 内部类可以直接访问外部类的成员,包括私有. - 外部类要访问内部类的成员,必须创建对象. - 外部类名.内部类名 对象名 = 外部类对象.内部类对象: - 例: class ...

  6. Ideal部署web工程

  7. 20165313 预备作业3 Linux安装及学习

    虚拟机安装 刚开始我觉得既然有了教程,安装虚拟机应该是很简单的事情,然而由于电脑本身系统地地问题,导致我数次安装失败,后来咨询了老师并查阅了资料,最终才安装好. 其中最主要的问题就是电脑虚拟化的修改. ...

  8. 《DSP using MATLAB》Problem 5.14

    说明:这两个小题的数学证明过程都不会,欢迎博友赐教. 直接上代码: %% +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ...

  9. mysql 常用函数-locate 和 instr 和 regexp

    ★1 -- 表级锁 情况SHOW STATUS LIKE 'table%';-- 行级锁 情况SHOW STATUS LIKE 'innodb_row_lock%'; -- 进程列表SHOW PROC ...

  10. Go Example--限速

    package main import ( "fmt" "time" ) func main() { requests := make(chan int, 5) ...