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 ...
随机推荐
- Logstash——multiline 插件,匹配多行日志
本文内容 测试数据 字段属性 按多行解析运行时日志 把多行日志解析到字段 参考资料 在处理日志时,除了访问日志外,还要处理运行时日志,该日志大都用程序写的,比如 log4j.运行时日志跟访问日志最大的 ...
- vue中通过WeixinJSBridge关闭微信公众号当前页面,返回微信公众号首页
之前有个需求,点击菜单进入到微信公众号模块,然后点击返回的时候不知道到哪里去,后来觉得点返回的时候直接关闭页面,但是window.close()并不能关闭页面,然后经过查找资料,发现通过以下方法可以 ...
- response.Close、response.End、response.Flush区别(下载文件)
今天在做文件下载功能用到的是response的方法,首先我们要了解这些方法的作用. 1.response.write():将信息写入http响应输出流. 2.response.Flush:向客户端发送 ...
- 关于 Java 关键字 volatile 的总结
1 什么是 volatile volatile 是 Java 的一个关键字,它提供了一种轻量级的同步机制.相比于重量级锁 synchronized,volatile 更为轻量级,因为它不会引起线程上下 ...
- 4 Linux文件与目录管理
Linux的目录文件结构为树状结构,最顶级目录为根目录 / 其他目录通过挂载可以将他们添加到树中,通过解除挂载可以移除他们 绝对路径: 根目录开始 eg: /usr/share/doc 相对路径: 不 ...
- flink dataset join笔记
1.dataset的join连接,通过key进行关联,一般情况下的join都是inner join,类似sql里的inner join key包括以下几种情况: a key expression a ...
- ORACLE ORION测试IO性能
https://www.oracle.com/technetwork/cn/topics/index-088165-zhs.html 下载地址 Orion是Oracle提供的IO性能测试工具,运行该工 ...
- uwsgi no python application found错误的解决(python3+centos6)
近期在努力把自己的项目从python2转到python3上,因为生产环境无法抛弃centos7,所以只好在centos7上安装了python3.装好了python3,将python命令软连接改成pyt ...
- Linux shell if条件判断2
前面介绍linux shell的if判断的语法,现在再补充一点. Linux shell if条件判断1 分支判断结构 if , case 下面两个结构语法,已经在前面有过示例. 结构1: ...
- nmap指令
-sP 主机发现 -p 端口扫描(可区域) -sV 端口(服务版本信息)-O 操作系统-iL 使用列表里的IP.(快捷方便)-iR 对公网上的随机n个IP.--excludeile ...