从C++ DLL导入函数的问题出在哪里

问题描述 投票:0回答:1

我正在尝试了解从 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++ 项目有问题。

c++ visual-studio dll inno-setup pascalscript
1个回答
1
投票

我被要求发布我的解决方案作为答案,所以这里是(注意,我不完全理解有关这个主题的所有内容,所以我只会发布你可能考虑的要点,如果你遇到与我):

  1. 使用x32发布模式构建你的DLL;
  2. 将您的代码包含在
    extern "C"
    选项中;
  3. __declspec(dllexport)
    关键字添加到函数声明中;
  4. 在 Pascal 脚本中使用
    cdecl
    约定;
  5. 在DLL路径中使用
    files:
    关键字;
  6. 另外,我注意到 Pascal 脚本在导出声明中只需要一个空格。例如,这一行(
    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;
© www.soinside.com 2019 - 2024. All rights reserved.