我声明了一些C函数原型如下:
extern "C" void __stdcall function();
我也有一些导出 function() 的第三方dll - 根本没有名字装饰 . 由于MinGW的stdcall @ -suffix,因为 undefined reference to function@... ,我无法构建我的exe或dll . 如何在没有@的情况下获取目标文件...只是简单的函数名称?
function()
undefined reference to function@...
这听起来像是一种将这些外部函数导出到MinGW的 gnu ld 链接器可以使用的正确导入库的方法,但它涉及创建一个 .def 定义文件 . 这样做的好处是,一旦你创建了一个合适的导入库,就不必使用 --add-stdcall-alias 或 --kill-at 之类的开关,因为导入库将包含编译器和链接器所需的符号 .
gnu ld
.def
--add-stdcall-alias
--kill-at
以下是执行此操作的过程的大致轮廓:
您需要一个工具调用 dlltool.exe ,它应该包含在与编译器相同的 MinGW/bin 目录中 .
dlltool.exe
MinGW/bin
你'll need to create a definition file (*.def) listing all the external functions you'对进口感兴趣 .
通过运行dlltool创建导入文件存根(* .a),传入您创建的.def文件作为输入 .
在构建项目时将新创建的导入文件* .a传递给链接器,以便正确解析符号 .
以下是定义文件的外观:
;Run the dlltool like this: ;dlltool -k -d third_party.def -l libthird_party.a LIBRARY third_party.dll EXPORTS dll_function1@0 dll_function2@8 dll_function3@16 ; ... dll_function_n@24
几个重要的事情要注意 . EXPORTS 部分必须按照工具链的预期以相同的名称修饰格式列出导出的符号/函数 . 在这种情况下,MinGW编译器和ld链接器期望 __stdcall C函数附加'@'后跟参数中的字节数 . 需要注意的第二个重要事项是 dlltool -k 将删除'@',它与您已经看到的 --kill-at 选项的功能相同 . 最终结果是您有一个具有正确内部名称装饰的导入库,因此事情可以正确解析,并且内部名称将映射到第三方dll中找到的导出的可见名称 .
EXPORTS
__stdcall
dlltool -k
最后一件事需要提及 . 在整个示例中,我们假设dll中未修饰的名称使用 __stdcall ,这不一定是真的 . 下面的图表(taken from here)显示了不同的编译器如何以不同的方式装饰 __cdecl 与 __stdcall :
__cdecl
MSVC DLL Call Convention | (dllexport) | DMC DLL | MinGW DLL | BCC DLL ---------------------------------------------------------------------------- __stdcall | _Function@n | _Function@n | Function@n | Function __cdecl | Function | Function | Function | _Function
您可以确保呼叫约定正确匹配,或者存在堆栈损坏和神秘程序崩溃的风险 .
man ld 为您提供 --enable-stdcall-fixup 选项,用于链接非@-装饰的库 . 我'm not sure if the leading underscores will be a problem, you'将不得不尝试 .
man ld
--enable-stdcall-fixup
如果你想用mingw生成目标文件或DLL,并希望导出名称没有"@", --kill-at 是你的朋友 .
2 回答
这听起来像是一种将这些外部函数导出到MinGW的
gnu ld
链接器可以使用的正确导入库的方法,但它涉及创建一个.def
定义文件 . 这样做的好处是,一旦你创建了一个合适的导入库,就不必使用--add-stdcall-alias
或--kill-at
之类的开关,因为导入库将包含编译器和链接器所需的符号 .以下是执行此操作的过程的大致轮廓:
您需要一个工具调用
dlltool.exe
,它应该包含在与编译器相同的MinGW/bin
目录中 .你'll need to create a definition file (*.def) listing all the external functions you'对进口感兴趣 .
通过运行dlltool创建导入文件存根(* .a),传入您创建的.def文件作为输入 .
在构建项目时将新创建的导入文件* .a传递给链接器,以便正确解析符号 .
以下是定义文件的外观:
几个重要的事情要注意 .
EXPORTS
部分必须按照工具链的预期以相同的名称修饰格式列出导出的符号/函数 . 在这种情况下,MinGW编译器和ld链接器期望__stdcall
C函数附加'@'后跟参数中的字节数 . 需要注意的第二个重要事项是dlltool -k
将删除'@',它与您已经看到的--kill-at
选项的功能相同 . 最终结果是您有一个具有正确内部名称装饰的导入库,因此事情可以正确解析,并且内部名称将映射到第三方dll中找到的导出的可见名称 .最后一件事需要提及 . 在整个示例中,我们假设dll中未修饰的名称使用
__stdcall
,这不一定是真的 . 下面的图表(taken from here)显示了不同的编译器如何以不同的方式装饰__cdecl
与__stdcall
:您可以确保呼叫约定正确匹配,或者存在堆栈损坏和神秘程序崩溃的风险 .
man ld
为您提供--enable-stdcall-fixup
选项,用于链接非@-装饰的库 . 我'm not sure if the leading underscores will be a problem, you'将不得不尝试 .如果你想用mingw生成目标文件或DLL,并希望导出名称没有"@",
--kill-at
是你的朋友 .