将 DLL 导入 Inno Setup 时出现问题
我正在 Inno Setup 安装脚本中导入 C++ DLL。 DLL代码如下:
void __stdcall SetFbParam(
char *dbFileName,char *dbTableName,char *dbParamName,char *dbParamValue) {
// of no use here and doesn't change anything
}
在Inno Setup中,我使用导入它
procedure FBset(dbFileName,dbTableName,dbParamName,dbParamValue: String;);
external 'SetFbParam@files:MyDll.dll stdcall setuponly';
但是,在启动安装程序期间我总是收到运行时错误,说它无法导入我的dll。我尝试了各种调用约定,但总是失败。 如果它很重要的话,我正在运行带有 UAC 的 Win7 x64(安装程序请求权限提升,然后崩溃)。
确切的消息是:
错误
运行时错误(-1:0):
无法导入
dll:C:\Users\Nevod\AppData\Local\Temp\is-6LOEC.tmp\MyDll.dll
dll 就在那里。
谢谢!
I am importing an C++ DLL in an Inno Setup install script. The DLL code is as follows:
void __stdcall SetFbParam(
char *dbFileName,char *dbTableName,char *dbParamName,char *dbParamValue) {
// of no use here and doesn't change anything
}
In the Inno Setup, I import it using
procedure FBset(dbFileName,dbTableName,dbParamName,dbParamValue: String;);
external 'SetFbParam@files:MyDll.dll stdcall setuponly';
However, I always get a runtime error during launch of the installer, saying that it cannot import my dll. I tried it with various calling conventions, but it always fails.
If it's of any importance, I'm running Win7 x64 with UAC on (the installer requests rights elevation and crashes after that).
The exact message is:
Error
Runtime error (at -1:0):
Cannot import
dll:C:\Users\Nevod\AppData\Local\Temp\is-6LOEC.tmp\MyDll.dll
The dll is there.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
MyDll.dll
是 32 位吗?MyDll.dll
是否依赖于同一目录中的任何其他 DLL?如果是这样,您需要在MyDll.dll
之后列出这些 DLL 的名称,以确保它们在MyDll.dll
之前提取已加载,您可能还需要loadwithalteredsearchpath
选项。 帮助中的示例:Is
MyDll.dll
32-bit?Does
MyDll.dll
depend on any other DLLs in the same directory? If so, you need to list the name(s) of those DLLs afterMyDll.dll
to ensure that they are extracted beforeMyDll.dll
is loaded, and you likely need theloadwithalteredsearchpath
option as well. Example from the help:(我知道它很旧,但也许其他一些也碰到了这个)
最有可能的是该函数的名称在 C++ DLL 中被破坏了。我也遇到了同样的问题,重新编译dll就解决了。简而言之:
如果您从 C++ 导出类似的内容:
您将得到一个名为 (Visual Studio) 的函数:
为了防止名称修改,您应该使用
extern "C"
指令。示例(Visual Studio)但是我发现 Visual Studio 将继续损坏,并且您会得到类似以下内容:
我能够获得干净名称的唯一方法解释如下:
C++ DLL 导出:装饰/损坏的名称
罪魁祸首确实是
__stdcall
。如果您从声明中删除它:您将再次获得干净的导出,即使没有 DEF 文件。 IMO 这应该足够好了,因为上面的代码声明了一个“C”导出函数,并且 C 的默认调用约定是 stdcall。然而,我没有时间和配置来验证这一点,因为添加 DEF 文件比导航 asm 代码和检查堆栈指针要容易得多:)
(I know it is old but maybe some other hits this one too)
Most probably the name of the function is mangled in the C++ DLL. I had the same problem and I was able to solve it by recompiling the dll. In short:
If you export from C++ something like:
you will get a function called (Visual Studio):
To prevent name mangling you should use
extern "C"
directive. Example (Visual Studio)However I have found that Visual Studio will continue to mangle and you get something like:
The sole way I was able to get clean names is explained here:
C++ DLL Export: Decorated/Mangled names
And the culprit is indeed
__stdcall
. If you remove that from your declaration:you will again get a clean export, even without a DEF file. IMO this should be good enough, as the code above declares a "C" exported function and the default calling convention for C is stdcall. However I haven't had the time and disposition to validate this as adding a DEF file is way easier than navigating asm code and check stack pointers :)
为了在 Inno Setup 的
[Code]
部分中使用 DLL,请确保:extern "C" __declspec( dllexport )
修饰符
cdecl
调用约定,因为stdcall
会破坏名称(https://learn.microsoft.com/en-us/cpp/cpp/stdcall)。当然,可以在 Inno Setup 导入语句中指定损坏的名称。但使用cdecl
似乎更容易。In order to use DLLs in Inno Setup's
[Code]
section please make sure:extern "C" __declspec( dllexport )
modifier
cdecl
calling convention becausestdcall
mangles name (https://learn.microsoft.com/en-us/cpp/cpp/stdcall). Of course it is possible to specify mangled name in Inno Setup import statement. But it seems easier to just usecdecl
.正如其他答案中提到的,不要忘记嵌入 DLL 的所有依赖项。不过,如果它是您的 DLL,最好摆脱(或至少减少)依赖关系。
例如,在 Visual Studio 中构建 C++ DLL 时,静态链接运行时,而不是动态链接。
在项目属性中,转到C/C++ >代码生成>运行时库并选择多线程(不是DLL)。
还有一些工具可以嵌入其他外部依赖项。
请参阅在已编译的可执行文件中嵌入 DLL
As mentioned in other answers, do not forget to embed all dependencies of your DLL. Though if it is your DLL, better might be to get rid of (or at least reduce) the dependencies.
For example when building C++ DLL in Visual Studio, link the runtime statically, not dynamically.
In project Properties, go to C/C++ > Code Generation > Runtime Library and select Multi-threaded (not DLL).
There are also tools that can embed other external dependencies.
See Embedding DLLs in a compiled executable