1

我声明了一些原型化的 C++ 函数,如下所示:

extern "C" void __stdcall function();

我也有一些导出的第三方 dll function()- 根本没有名称装饰。undefined reference to function@...由于 MinGW 的 stdcall @-suffix,我无法构建我的 exe 或 dll 。如何在没有 @... 的情况下获取目标文件,只是简单的函数名?

4

2 回答 2

6

听起来您正在尝试使用 MinGW 编译使用来自第三方 dll 的外部 C 函数的程序。有一种方法可以将这些外部函数导出到 MinGW 的链接器可以使用的正确导入库中,gnu ld但它涉及创建.def定义文件。这样做的好处是,一旦您创建了一个适当的导入库,您就不必摆弄诸如此类的开关,--add-stdcall-alias或者--kill-at因为导入库将包含编译器和链接器所期望的符号。

以下是执行此操作的过程的粗略概述:

  1. 您将需要一个工具调用,该工具调用dlltool.exe应包含在与MinGW/bin编译器相同的目录中。
  2. 您需要创建一个定义文件 (*.def),列出您有兴趣导入的所有外部函数。
  3. 通过运行 dlltool 并传入您创建的 .def 文件作为输入来创建导入文件存根 (*.a)。
  4. 在构建项目时将新创建的导入文件 *.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 链接器期望C 函数附加一个“@”,后跟参数中的字节数。需要注意的第二件重要事情是,它将删除“@”,它与您已经看到的选项具有相同的作用。这样做的最终结果是您有一个具有正确内部名称装饰的导入库,因此事情可以正确解决,并且该内部名称将映射到在您的 3 rd方 dll中找到的导出可见名称。__stdcalldlltool -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

确保调用约定正确匹配或冒着堆栈损坏和神秘程序崩溃的风险由您决定。

于 2012-01-27T11:42:14.680 回答
4

man ld为您 --enable-stdcall-fixup提供链接非@装饰库的选项。我不确定前导下划线是否会成为问题,您必须尝试。

如果您想使用 mingw 生成目标文件或 DLL,并希望导出名称不带“@”,那--kill-at是您的朋友。

于 2011-11-09T13:34:25.063 回答