MinGW g++.exe 编译 DLL 时,导出函数名带@的问题
今天尝试用CodeBlocks写了一个简单的Dll,发现生成的 dll 文件导出的函数名后面都有一个 @xxx
从生成的 libDll2.def 中看到:
EXPORTS
DllMain@ @
Max@ @
SomeFunction@ @
funReturnStr2@ @
funReturnStr@ @
updateInt2@ @
updateInt@ @
updateStr@ @
至于为什么导出的函数名后面会带@的解释:
_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@ @
Max = Max@ @
SomeFunction = SomeFunction@ @
funReturnStr = funReturnStr@ @
funReturnStr2 = funReturnStr2@ @
updateInt = updateInt@ @
updateInt2 = updateInt2@ @
updateStr = updateStr@ @
这个时候,在另一个应用程序中,加载 Dll2.dll 后,调用 Dll2 中的函数 Max 的正确写法就变成理想中的:
GetProcAddress(hDll, "Max");
扩展资料:https://www.cnblogs.com/jiftle/p/8451336.html (DLL编写中extern “C”和__stdcall的作用)
完。
名品推荐:达尔丽 蚕美人 多俏美 美腾 岱之青 斯芭艺 康爵 绅诺 爱森狼 强人
MinGW g++.exe 编译 DLL 时,导出函数名带@的问题的更多相关文章
- js里调用函数时,函数名带括号与不带括号的区别
function test(){ return 1;}var a=test;console.log(a);//输出[Function: test]var b=test();console.log(b) ...
- dll 导出函数名的那些事
dll 导出函数名的那些事 关键字: VC++ DLL 导出函数 经常使用VC6的Dependency或者是Depends工具查看DLL导出函数的名字,会发现有DLL导出函数的名字有时大不相同,导 ...
- DLL中导出函数的两种方式(dllexport与.def文件)
DLL中导出函数的声明有两种方式: 一种方式是:在函数声明中加上__declspec(dllexport): 另外一种方式是:采用模块定义(.def)文件声明,(.def)文件为链接器提供了有关被链接 ...
- DLL声明导出函数的两种方式
DLL中导出函数的声明有两种方式:一种为在函数声明中加上__declspec(dllexport):另外一种方式是采用模块定义(.def) 文件声明,.def文件为链接器提供了有关被链接程序的导出.属 ...
- (转)DLL中导出函数的两种方式(dllexport与.def文件)
DLL中导出函数的两种方式(dllexport与.def文件)http://www.cnblogs.com/enterBeijingThreetimes/archive/2010/08/04/1792 ...
- 【转】DLL中导出函数的两种方式(dllexport与.def文件)
DLL中导出函数的两种方式(dllexport与.def文件) DLL中导出函数的声明有两种方式: 一种方式是:在函数声明中加上__declspec(dllexport):另外一种方式是:采用模块定义 ...
- DLL的导出函数重定向机制
曾经,调试时跟进HeapAlloc,结果发现直接进入到ntdll的RtlAllocateHeap中,感到很有趣,就使用Dependency Walker查看kernel32.dll的导出函数,结果发现 ...
- C++ 动态库导出函数名“乱码”及解决
C++ 动态库导出函数名“乱码”及解决 刚接触C++,在尝试从 dll 中导出函数时,发现导出的函数名都“乱码”了. 导出过程如下: 新建一个Win32项目: 新建的解决方案里有几个导出的示例: // ...
- 【图文】[新手]C++ 动态库导出函数名“乱码”及解决
刚接触C++,在尝试从 dll 中导出函数时,发现导出的函数名都"乱码"了. 导出过程如下: 新建一个Win32项目: 新建的解决方案里有几个导出的示例: // 下列 ifdef ...
随机推荐
- Jackson 序列化/反序列化时忽略某属性
https://www.iteye.com/blog/wwwcomy-2397340 博客分类: Spring jacksonread_onlyjsonignore 基于Spring MVC的RES ...
- Ubuntu 16.04 ssh协议连接root管理员用户
首先先给自己的Ubuntu 创建一个root密码.毕竟登陆的时候都是用户登陆的. 在 命令行中输入 sudo passwd // 设置root密码 password for func : //输入用 ...
- 记一个netcore HttpClient的坑
异常信息 The SSL connection could not be established, see inner exception ---> AuthenticationExceptio ...
- jQuery实现C#CheckBoxList模糊搜索
前言 最近开发的一套系统中需要对商品进行管理,在选择商品时,要分别从品牌.型号.商品三个类别分别选择对应的选项才能找到需要的商品,三者的关系为:品牌包含型号,型号包含商品,因此使用了三个不同的 asp ...
- Windows git和cmd代理设置
linux的比较简单,直接修改配置文件即可,这里就不再赘述 设置Git代理 http代理: 临时代理: export http_proxy=http://127.0.0.1:7777 export h ...
- 一款神器,批量手机号码归属地查询软件,支持导出Excel表格
很多人查询手机号码归属地,还在一个一个百度去查太慢了,如果有几万个那么是不是要百度很久 有一款软件很多人都不知道,可以吧号码复制进去,即使里面有汉字也可以把手机号码挑出来,然后查询归属地,还具有号码去 ...
- Java 之 Stack 集合
一.Stack:栈 概述 栈是一种先进后出(FILO)或后进先出(LIFO:Last in first out)的数据结构. Stack是Vector的子类,比Vector多了几个方法,它的后进先出的 ...
- vue+element 表格按需合并
这个功能难度感觉一般般吧,记录一下,以后碰到了直接来复制,懒得再写了 效果如下: 前6列是合并,后面的有几行,动态显示几行 重点是在数据处理上面做文章,合并列大家都会,数据处理呢?这样来处理, 我们拿 ...
- ELK日志系统之kibana的使用操作
1.ELK日志系统打开后,打开kibana的操作界面,第一步创建索引模式: 第2步:创建日志索引 第3步:创建成功 第4步:查看30分钟时间段内的日志数据,也可以查今天的,今月的,今年的 放牛去
- CMake相关代码片段
目录 用于执行CMake的.bat脚本 CMakeLists.txt和.cmake中的代码片段 判断平台:32位还是64位? 判断Visual Studio版本 判断操作系统 判断是Debug还是Re ...