我声明了一些原型化的 C++ 函数,如下所示:
extern "C" void __stdcall function();
我也有一些导出的第三方 dll function()
- 根本没有名称装饰。undefined reference to function@...
由于 MinGW 的 stdcall @-suffix,我无法构建我的 exe 或 dll 。如何在没有 @... 的情况下获取目标文件,只是简单的函数名?
我声明了一些原型化的 C++ 函数,如下所示:
extern "C" void __stdcall function();
我也有一些导出的第三方 dll function()
- 根本没有名称装饰。undefined reference to function@...
由于 MinGW 的 stdcall @-suffix,我无法构建我的 exe 或 dll 。如何在没有 @... 的情况下获取目标文件,只是简单的函数名?
听起来您正在尝试使用 MinGW 编译使用来自第三方 dll 的外部 C 函数的程序。有一种方法可以将这些外部函数导出到 MinGW 的链接器可以使用的正确导入库中,gnu ld
但它涉及创建.def
定义文件。这样做的好处是,一旦您创建了一个适当的导入库,您就不必摆弄诸如此类的开关,--add-stdcall-alias
或者--kill-at
因为导入库将包含编译器和链接器所期望的符号。
以下是执行此操作的过程的粗略概述:
dlltool.exe
应包含在与MinGW/bin
编译器相同的目录中。下面是定义文件的样子:
;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 链接器期望C 函数附加一个“@”,后跟参数中的字节数。需要注意的第二件重要事情是,它将删除“@”,它与您已经看到的选项具有相同的作用。这样做的最终结果是您有一个具有正确内部名称装饰的导入库,因此事情可以正确解决,并且该内部名称将映射到在您的 3 rd方 dll中找到的导出可见名称。__stdcall
dlltool -k
--kill-at
最后一件事需要提及。在整个示例中,我们假设dll 中未修饰的名称使用的__stdcall
是不一定正确的。下图(取自此处)显示了不同编译器的装饰方式__cdecl
与__stdcall
不同之处:
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
提供链接非@装饰库的选项。我不确定前导下划线是否会成为问题,您必须尝试。
如果您想使用 mingw 生成目标文件或 DLL,并希望导出名称不带“@”,那--kill-at
是您的朋友。