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 ...
随机推荐
- ******可用 SpringBoot 项目打包分开lib,配置和资源文件
spring-boot多模块打包后,无法找到其他模块中的类https://blog.csdn.net/Can96/article/details/96172172 关于SpringBoot项目打包没有 ...
- select2插件placeholder不显示的问题
如果设置了select2的templateSelection,没做特殊处理的话placeholder会不显示,需要做特殊处理 templateSelection: function(repo){ if ...
- 如何写出优雅的 Golang 代码
原文: https://draveness.me/golang-101.html Go 语言是一门简单.易学的编程语言,对于有编程背景的工程师来说,学习 Go 语言并写出能够运行的代码并不是一件困难的 ...
- WebSocket实现Web端即时通信
前言 WebSocket 是HTML5开始提供的一种在浏览器和服务器间进行全双工通信的协议.目前很多没有使用WebSocket进行客户端服务端实时通信的web应用,大多使用设置规则时间的轮询,或者使用 ...
- webapi 返回类型
参考 大神;https://www.cnblogs.com/landeanfen/p/5501487.html
- C# 构造基础返回值类型-BaseResponse
学无止境,精益求精 十年河东,十年河西,莫欺少年穷 用于基础返回值类型,如下: using System; using System.Collections.Generic; using System ...
- Java程序员的魔法杖-Arthas 3.1.2版本发布了
Arthas已经成为我日常运维.线上排查的必备之品,听说最近更新版本了,今天这篇文章看下又增加了什么新的能力. Arthas是Alibaba开源的Java诊断工具,深受开发者喜爱. Github:ht ...
- Oracle分析函数FIRST_VALUE、LAST_VALUE
FIRST_VALUE.LAST_VALUE分析函数可以按照特定分组和排序取出组内首尾值,语法 FIRST_VALUE { (expr) [ {RESPECT | IGNORE} NULLS ] | ...
- Jmeter 在 beanshell 脚本中写日志
JMETER 在执行时,会写日志数据,我们在编写脚本的时候也可以自己写日志. 日志记录再jmeter 的bin 目录的 jmeter.log 文件中. jmeter 比较人性化,它在这里提供了脚本可以 ...
- Linux内存含义
关于Linux的内存,首先要先知道各个部分的含义 1. 命令: free -m // Mb 显示 1,total:物理内存实际总量2,used:这块千万注意,这里可不是实际已经使用了的内存哦 ...