Delphi 10.3 -奇怪的DLL行为



我在使用Delphi和DLL时遇到了一个非常奇怪的行为。

我想学习如何创建和使用DLL。为此,我创建了两个文件:一个包含DLL,另一个调用它。

DLL从*.ini文件(getinfo函数)中检索信息。当在表单中调用它时,我得到以下错误:"访问冲突地址XXXXXXXX在"dlltest.dll"模块。读取地址00000000

我想尝试一些其他的东西,所以我创建了一个简单的过程,它只显示一条消息。

有趣的是,当我调用这个过程(其唯一目的是显示一条消息)时,我不再得到访问冲突错误。

我真的不明白它是如何使我的代码工作的。我真的希望有人能给我解释一下。我使用Delphi 10.3 Rio Version 26.0.36039.7899

下面是我生成的代码:

dlltest:

library dlltest;
uses
System.SysUtils, System.Classes, System.IniFiles, Winapi.Windows, vcl.dialogs;
var
// Ini file var
iniConfig: TInifile;
procedure SayHello;
var
hello: PChar;
begin
hello := 'Hello world!';
ShowMessage(hello);
end;
// -----------------------------------------------------------------------------
// Retrieving .ini file
function GetIni: TInifile;
begin
result := TInifile.Create('.monitoring.ini');
end;
// -----------------------------------------------------------------------------
function GetInfos: ShortString;
begin
iniConfig := GetIni;
try
result := iniConfig.ReadString('filename', 'start', 'start');
finally
iniConfig.Free;
end; { try }
end; { function GetInfos }
exports
SayHello, GetInfos;
begin
end.

使用dll:

unit testUtilisationDll;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils,
System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms,
Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Déclarations privées }
public
{ Déclarations publiques }
end;
var
Form1: TForm1;
procedure SayHello; StdCall; external 'dlltest.dll';
function GetInfos: ShortString; StdCall;
external 'dlltest.dll';
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
SayHello;
ShowMessage(GetInfos(self));
end;
end.

当您导出函数时,它们使用默认调用约定(Register),而当您导入它们时,您告诉导入它们使用StdCall调用约定。

DLL导出函数的正常情况是StdCall约定,所以你应该在你的.DLL源代码中声明你的函数使用这个调用约定:

function GetInfos: ShortString; stdcall;

procedure SayHello; stdcall;
另一个问题是当你调用getinfo:
ShowMessage(GetInfos(self));

你给它传递了一个参数(self),但是你的import声明:

function GetInfos: ShortString; StdCall; external 'dlltest.dll';

没有列出任何参数。您将无法编译程序,因为它显示在你的问题…

最新更新