我正在尝试了解从 DLL 导入函数是如何工作的。我使用向导创建了一个 Inno Setup 脚本:
[Files]
Source: "TestDll\x64\Release\TestDll.dll"; Flags: dontcopy;
[Code]
procedure MyDllFunc(hWnd: Integer; lpText, lpCaption: AnsiString; uType: Cardinal);
external '[email protected] stdcall delayload setuponly';
function TestBool() : Boolean;
external '[email protected] stdcall delayload setuponly';
procedure InitializeWizard;
var
TestVar: Boolean;
hWnd: Integer;
begin
Log('InitializeWizard');
TestVar := TestBool();
if TestVar then begin
Log('TestVar: True');
end;
hWnd := StrToInt(ExpandConstant('{wizardhwnd}'));
MyDllFunc(hWnd, 'Hello from custom DLL function', 'MyDllFunc', MB_OK);
end;
DLL 是使用 MS Visual Studio 2022 创建的,C++ 项目创建为“动态链接库 (DLL)”项目,
MyDllFunc
函数的代码是从 Inno Setup 示例复制的,这里是 dll 的代码:
// dllmain.cpp
#include <windows.h>
void __stdcall MyDllFunc(HWND hWnd, char *lpText, char *lpCaption, UINT uType)
{
MessageBoxA(hWnd, lpText, lpCaption, uType);
}
bool __stdcall TestBool()
{
return true;
}
运行 Inno Setup 脚本时,我总是收到两个导入函数的错误:
运行时错误。第 43 行:无法调用 proc。
有关 DLL 的 Inno Setup 日志摘录:
[16:08:04.542] -- DLL function import --
[16:08:04.567] Function name: MyDllFunc
[16:08:04.570] DLL name: setup:TestDll.dll
[16:08:04.571] Dest DLL name: TestDll.dll
[16:08:04.571] Importing the DLL function.
[16:08:04.572] Successfully imported the DLL function. Delay loaded? Yes
[16:08:04.572] -- DLL function import --
[16:08:04.573] Function name: TestBool
[16:08:04.573] DLL name: setup:TestDll.dll
[16:08:04.574] Dest DLL name: TestDll.dll
[16:08:04.575] Importing the DLL function.
[16:08:04.575] Successfully imported the DLL function. Delay loaded? Yes
但是,Inno Setup 示例“CodeDll.iss”正在运行。所以我可以假设我的 C++ 项目有问题。
我被要求发布我的解决方案作为答案,所以这里是(注意,我不完全理解有关这个主题的所有内容,所以我只会发布你可能考虑的要点,如果你遇到与我):
extern "C"
选项中;__declspec(dllexport)
关键字添加到函数声明中;cdecl
约定;files:
关键字;cdecl
和 delayload
– external 'TestBool@files:TestDll.dll cdecl delayload setuponly';
之间有 2 个空格) – 将触发错误。这是适合我的完整代码:
// dllmain.cpp
#include <windows.h>
extern "C"
{
void __declspec(dllexport) MyDllFunc(HWND hWnd, char *lpText, char *lpCaption, UINT uType)
{
MessageBoxA(hWnd, lpText, lpCaption, uType);
}
bool __declspec(dllexport) TestBool()
{
return true;
}
}
Inno 安装脚本:
[Files]
Source: "TestDll\Release\TestDll.dll"; Flags: dontcopy;
[Code]
procedure MyDllFunc(hWnd: Integer; lpText, lpCaption: AnsiString; uType: Cardinal);
external 'MyDllFunc@files:TestDll.dll cdecl delayload setuponly';
function TestBool() : Boolean;
external 'TestBool@files:TestDll.dll cdecl delayload setuponly';
procedure InitializeWizard;
var
TestVar: Boolean;
hWnd: Integer;
begin
Log('InitializeWizard');
TestVar := TestBool();
if TestVar then begin
Log('TestVar: True');
end;
hWnd := StrToInt(ExpandConstant('{wizardhwnd}'));
MyDllFunc(hWnd, 'Hello from custom DLL function', 'MyDllFunc', MB_OK);
end;