【问题标题】:mingw32 g++ and stdcall @suffixmingw32 g++ 和 stdcall @suffix
【发布时间】:2011-12-25 05:13:22
【问题描述】:

我声明了一些 C++ 函数原型如下:

extern "C" void __stdcall function();

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

【问题讨论】:

    标签: c++ linker mingw name-decoration stdcall


    【解决方案1】:

    听起来您正在尝试使用 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 链接器期望 __stdcall C 函数附加一个 '@',后跟参数中的字节数。第二个需要注意的重要事情是dlltool -k 将删除'@',这与您已经看到的--kill-at 选项的作用相同。这样做的最终结果是您有一个具有正确内部名称装饰的导入库,因此事情会正确解决,并且该内部名称将映射到您的 3rd 中找到的导出可见名称 方 dll。

    最后一件事需要提及。在整个示例中,我们假设 dll 中未修饰的名称使用__stdcall,这不一定是正确的。下图 (taken from here) 显示了不同的编译器对 __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
    

    您需要确保调用约定正确匹配,否则有堆栈损坏和神秘程序崩溃的风险。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 不,这不起作用。此外,如果我没记错的话,stdcall fixups 会在适用的情况下自动运行,并且只需使用 --disable。我正在寻找的是删除@
      • 当你想链接@'s时,这就是stdcall修复的用途。或者你想用 mingw 构建一个 DLL 并且没有用 @'s 导出的符号?
      • 正如我之前所说,我有一些带有导出函数的第三方 dll(并且这个函数可能必须通过 stdcall 调用 - 因为它在一些旧的 VisualBasic 示例中使用)并且根本没有任何装饰和我写了 C++ 外部函数。我真正需要的是没有@-suffix 的目标文件。通过这种方式,我可以对其进行两次测试:1) 通过 c++ 执行,2) 在 VisualBasic 中测试我的 c++ 中间体,以消除一些可能与指针等相关的问题。但是没有任何效果,我尝试过 g++ 选项,objcopy,...
      • 所以一种可能性是 --add-stdcall-alias,这样可以在没有(和有)@-suffix 的情况下获得对象。我已经尝试过了,但它现在才有效(也许链接器的选项最后?)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-11
      • 2014-03-31
      • 2014-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多