在我的项目中我有一个Windows应用程序和一个DLL。我写过dll所以:
library MyDLL;
uses
System.SysUtils,
System.Classes;
{$R *.res}
function Prova: string; export;
begin
result := 'prova';
end;
exports Prova;
begin
end.
并且在主程序中我调用了例程:
unit FrmMain;
interface
uses
// declaration uses //
function Prova: string; external 'MyDLL.dll';
type
// declaration type //
implementation
begin
...
TAdvEdit1.Text := Prova; // [1] //
...
end;
end.
当我编译所有项目时没有报告错误,并且状态报告SUCCESS,但是应用程序无法启动。 如果我删除行[1],它可以正常工作。通常,当我调用函数Prova时,应用程序无法启动。 我能解决这个问题吗?非常感谢。
答案 0 :(得分:3)
您描述的行为是您的应用程序无法加载时会发生的行为。从调试器运行时,您会收到静默故障。在没有调试器的情况下运行时,您将看到一条错误消息“应用程序无法初始化...”。这将提供详细信息。
在您的情况下,似乎可能的原因是库加载器无法解析DLL的依赖性。这就是当删除对外部函数的调用时应用程序运行的原因。删除该调用时,还会删除对外部DLL的依赖性。通过确保可以加载DLL来解决问题。例如,将其放在与可执行文件相同的目录中。
调试器的静默失败令人沮丧。一旦你经历了几次,你就会知道该怎么做 - 在没有调试器的情况下运行,找出真正出错的地方。
我还建议您不要跨模块边界传递托管Delphi字符串。这将迫使您对可执行文件和DLL使用相同的编译器。如果您要接受该约束,那么您也可以使用包。正如您的代码所代表的那样,它需要使用ShareMem才能工作。但我不建议这样做。
答案 1 :(得分:2)
您的程序和DLL具有单独的内存管理器。作为一般规则,不应在应用程序内部使用从DLL分配的内存(反之亦然)。 分配来自哪里?在Delphi中,“string”是托管类型,即当您将一些文本分配给字符串变量时(在您的情况下结果:='prova'),Delphi(在场景后面)使用DLL的内存管理器为该字符串分配内存。然后,例如,如果您在主应用程序中分配其他文本值,则重新分配使用应用程序的内存管理器,这是坏的,即应用程序的MM正在触摸它尚未分配的内存。
要解决此问题,您必须在“应用程序(。dpr文件)中包含”SimpleShareMem“(Delphi> = 2010 IIRC?)单元作为您的USES子句的第一个单元。 DLL:
library MyDLL;
uses
SimpleShareMem, // **MUST BE THE FIRST UNIT**
System.SysUtils,
System.Classes;
...
program YourApp;
uses
SimpleShareMem, // **MUST BE THE FIRST UNIT**
// declaration uses //
可以在“Start > Programs > Embarcadero RAD Studio > Samples > Delphi > RTL > SimpleShareMem”
中找到此方法的示例您还可以使用PCHAR在DLL和APP之间传输字符串。