• MinGW g++.exe 编译 DLL 时,导出函数名带@的问题


    https://www.cnblogs.com/personnel/p/11275690.html
    今天尝试用CodeBlocks写了一个简单的Dll,发现生成的 dll 文件导出的函数名后面都有一个 @xxx

    从生成的 libDll2.def 中看到:

    EXPORTS
        DllMain@12 @1
        Max@8 @2
        SomeFunction@4 @3
        funReturnStr2@4 @4
        funReturnStr@0 @5
        updateInt2@4 @6
        updateInt@4 @7
        updateStr@4 @8
    

    至于为什么导出的函数名后面会带@的解释:

    _stdcall调用约定的函数会有@,后面的数字表示参数总共所占字节数,这是因为_stdcall函数需要被调用者清空堆栈,所以需要知道参数所占大小。

    _cedcl调用约定的函数没有@及后面的数字,因为_cedcl调用约定的函数由调用者清空堆栈。

    来源:https://bbs.csdn.net/topics/380193271

    此时,如果在别的应用程序中加载这个dll,调用Max函数时,需要使用:GetProcAddress(hDll, "Max@8");

    这种写法,让人感觉不太爽。

    那么使用 MinGW g++.exe 如何让编译后的dll中的函数名不要带@呢?

    一开始,我找到这篇介绍: https://www.cnblogs.com/lichmama/p/4126323.html (MinGW(GCC)编译DLL文件)

    其中提到:

    发现gcc可以在链接阶段通过指定 --kill-at 参数来消除这种情况。
    
    d:\test>
    #执行编译命令
    d:\test>mingw32-gcc -c -DBUILD_DLL mydll.c
    #执行链接命令,生成mydll.dll和静态库文件libmydll.a
    d:\test>mingw32-gcc -shared -o mydll.dll mydll.o -Wl,--kill-at,--out-implib,libmydll.a
    Creating library file: libmydll.a
    

    根据提示,我在CodeBlocks 中进行设置:
    错误截图不上传

    然后编译的时候,提示:

    mingw32-g++.exe -O2 -Wall -DBUILD_DLL -c D:\soft\c\Dll2\main.cpp -o obj\Release\main.o
    mingw32-g++.exe -shared -Wl,--output-def=bin\Release\libDll2_test.def -Wl,--out-implib=bin\Release\libDll2_test.a -Wl,--dll obj\Release\main.o -o bin\Release\Dll2.dll -s --kill-at -luser32
    mingw32-g++.exe: error: unrecognized command line option '--kill-at'

    ---> 无法识别的命令行选项'--kill-at'

    什么情况?

    我看到上面的这篇文章中使用的是:mingw32-gcc,而我现在用到的是 mingw32-g++.exe,难道是编译程序的不同造成的?

    我对gcc的命令行参数本来就不了解,我就继续上网搜索...

    然后找到这一篇:https://www.linuxidc.com/Linux/2015-12/126123.htm (MinGW 使用和创建 DLL 应注意的问题)

    其中,我看到这么一句:

    MinGW 如何创建一个标准的 DLL。MinGW 中创建标准 DLL,应该使用 __declspec(dllexport),包括 extern "C" 等都是和 VC 一样的。
    但要注意,这样编译链接生成的 DLL,导出的函数名尾部都带有 @nn,为了要去除它们,必须在链接器参数设置中使用 -Wl,--kill-at,它告诉链接器创建 DLL 时导出的函数名尾部不要带有 @nn。
    注,在 NetBeans CDT 中,上面这个参数同样是在链接器参数设置中指定。
    然后,我就重新设置了一下CodeBlocks:

    再次编译,成功。

    搞了半天,我少写了 -Wl, 然后我就百度了一下 -Wl,看到解释:https://blog.csdn.net/wang_hufeng/article/details/53899120 (gcc编译选项-Wl)

    -Wl 选项告诉编译器将后面的参数传递给链接器。
    编译 dll 成功后,再次打开 libDll2.def 查看函数定义:

    EXPORTS
        DllMain = DllMain@12 @1
        Max = Max@8 @2
        SomeFunction = SomeFunction@4 @3
        funReturnStr = funReturnStr@0 @4
        funReturnStr2 = funReturnStr2@4 @5
        updateInt = updateInt@4 @6
        updateInt2 = updateInt2@4 @7
        updateStr = updateStr@4 @8
    

    这个时候,在另一个应用程序中,加载 Dll2.dll 后,调用 Dll2 中的函数 Max 的正确写法就变成理想中的:

    GetProcAddress(hDll, "Max");

    扩展资料:https://www.cnblogs.com/jiftle/p/8451336.html (DLL编写中extern “C”和__stdcall的作用)

    完。

  • 相关阅读:
    vue中处理过内存泄露处理方法
    Nuxt2.x项目实战相关问题记录
    Android 7.0+模拟器Fiddler抓包详细教程 fiddler443问题解决办法
    inspeckage
    yile接口
    入坑Vue(二)Node.js环境安装
    入坑Vue(一)简介
    入库Vue(三) vuecli全局安装,创建Vue项目
    入坑vue(三)安装VSCode
    入坑Vue(四) 引用element ui组件,配置登录
  • 原文地址:https://www.cnblogs.com/marklove/p/16265231.html
Copyright © 2020-2023  润新知