【发布时间】:2019-10-02 05:26:28
【问题描述】:
我有一个用 x86 汇编语言编写的 DLL。所有导出都引用stdcall 函数。所有出口均未装饰。
我特别需要使用导入库将这个 DLL 按原样链接到 C 项目。 LoadLibrary 或更改导出名称等不是一种选择。
我有两个问题
- 当我从具有导出名称的 DEF 文件为 DLL 创建导入库 (.lib) 文件时,所有名称都被修饰为
cdecl!我找不到将它们指定为未装饰stdcall的方法。 DLL 中不存在这些修饰名称,因此在运行时,即使可以编译也不会起作用。 - 当我在 MSVC 中编写代码调用 DLL 函数时,无论是否指定 stdcall,编译器都会修改函数的名称。所以对
ExampleFunction的调用变成了_ExampleFunction@12,我只需要它是ExampleFunction。
幸运的是,我需要的东西必须是可能的,因为 Windows 系统 DLL(例如 kernel32.dll、user32.dll 等)遵循完全相同的约定。每个导出的函数都是 stdcall 并且没有修饰。
我已经读过这个:https://qualapps.blogspot.com/2007/08/how-to-create-32-bit-import-libraries.html
我遇到了这些问题:
- 使用
extern "C"不适用于此处,因为这是一个 C 项目。该说明符甚至不起作用,尽管这是一个 C 项目,但名称还是会被修改。 - 从只包含原始函数名称的 DEF 文件创建 .lib 文件不起作用。名称被修改。
example-lib.def 文件如下所示:
LIBRARY example-lib.dll
EXPORTS
ExampleFunction
.lib 文件是用这个命令生成的:
lib.exe /def:example-lib.def /OUT:example-lib.lib
使用dumpbin.exe /headers example-lib.lib时lib文件中的入口是这样的
Version : 0
Machine : 14C (x86)
TimeDateStamp: 5CDBA30C Wed May 15 06:26:36 2019
SizeOfData : 00000016
DLL name : example-lib.dll
Symbol name : _ExampleFunction
Type : code
Name type : no prefix
Hint : 20
Name : ExampleFunction
我通过以下声明来导入:
extern void __stdcall ExampleFunction(int a, int b, int c);
我这样调用函数:
ExampleFunction(1, 2, 3);
它所在的 lib 文件和目录在 VC 项目设置中指定。
当调用ExampleFunction 的代码编译时,链接器不会完成,因为它在我的DEF 文件中找不到_ExampleFunction@12。即使在 DEF 文件中,程序也不会运行,因为_ExampleFunction@12 没有在实际 DLL 的导出部分中导出。只导出普通的ExampleFunction。
那么如何让 C 程序从 DLL 中调用 ExampleFunction 呢?当 C 项目从 user32.dll 调用函数时,这是如何完成的?我可以使用相同的程序来实现这一点吗?
【问题讨论】:
-
在这里使用 def 文件。请展示一个完整但最小的示例。
-
@DavidHeffernan DLL 的 DEF 文件如下所示。有没有办法告诉
lib.exeExampleFunction 是未修饰的标准调用?LIBRARY example-dll EXPORTS ExampleFunction -
@manuell 是的,这是我开始制作 lib 文件时看到的第一件事。
-
@DavidHeffernan 我现在已经扩展了这个问题以包含一个可重现的示例。
标签: c dll dllimport calling-convention