C++ 动态库导出函数名“乱码”及解决
C++ 动态库导出函数名“乱码”及解决
刚接触C++,在尝试从 dll 中导出函数时,发现导出的函数名都“乱码”了。
导出过程如下:
新建一个Win32项目:

新建的解决方案里有几个导出的示例:
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DLLEXPORT_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// DLLEXPORT_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef DLLEXPORT_EXPORTS
#define DLLEXPORT_API __declspec(dllexport)
#else
#define DLLEXPORT_API __declspec(dllimport)
#endif // 此类是从 dllExport.dll 导出的
class DLLEXPORT_API CdllExport {
public:
CdllExport(void);
// TODO: 在此添加您的方法。
}; extern DLLEXPORT_API int ndllExport; DLLEXPORT_API int fndllExport(void);
于是我什么都不做,直接生成,并且在C#里导入看看能否调用,嗯……错误来了:

找不到入口点?难道是没导出么?我们用“Dependency Walker”来看看:

Oh, shit, WTF is this? 导出是导出了,不过怎么都乱码了?
右键选择“Undecorate C++ Functions”之后才出现了真面目:

不过我们的目的是要在C#中使用,而不是用眼睛在 Dependency 里面看啊!嗯,既然入口点的名字都变了,要不我们在 C# 中手动指定入口点试试?

不错,成功了,我们终于可以使用 C++ dll里导出的函数了。
不过,这些乱码到底是什么东西?百度一下很轻松地找到了答案:
DLL(动态库)导出函数名乱码含义
C++编译时函数名修饰约定规则:
__stdcall调用约定:
1、以"?"标识函数名的开始,后跟函数名;
2、函数名后面以"@@YG"标识参数表的开始,后跟参数表;
3、参数表以代号表示:
X--void
D--char
E--unsigned char
F--short
H--int
I--unsigned int
J--long
K--unsigned long
M--float
N--double
_N--bool
....
PA--表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以"0"代替,一个"0"代表一次重复;
4、参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前;
5、参数表后以"@Z"标识整个名字的结束,如果该函数无参数,则以"Z"标识结束。
其格式为"?functionname@@YG*****@Z"或"?functionname@@YG*XZ",例如
int Test1(char *var1, unsigned long)-----?Test1@@YGHPADK@Zvoid Test2()-----"?Test2@@YGXXZ"
__cdecl调用约定:
规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YA"。
__fastcall调用约定:
规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YI"。如果要用DEF文件输出一个"C++"类,则把要输出的数据和成员的修饰名都写入.def模块定义文件
所以... 通过def文件来导出C++类是很麻烦的,并且这个修饰名是不可避免的
虽然有约定的含义,但这也真够麻烦的!我不禁想,我们之前导入 User32.dll,Shell32.dll 等等这些动态库的函数的时候,那些EntryPoint没见这么麻烦啊,怎么回事?还是万能的百度……“在到处函数之前加上“extern "C"”就行了!”,我们来试试:
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DLLEXPORT_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// DLLEXPORT_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef DLLEXPORT_EXPORTS
#define DLLEXPORT_API __declspec(dllexport)
#else
#define DLLEXPORT_API __declspec(dllimport)
#endif // 此类是从 dllExport.dll 导出的
class DLLEXPORT_API CdllExport {
public:
CdllExport(void);
// TODO: 在此添加您的方法。
}; extern "C" DLLEXPORT_API int ndllExport; extern "C" DLLEXPORT_API int fndllExport(void);
注意和之前对比,最后两行有变化。编译生成,运行 C# 项目:

没有指定 EntryPoint 了,成功!
C++ 动态库导出函数名“乱码”及解决的更多相关文章
- 【图文】[新手]C++ 动态库导出函数名“乱码”及解决
刚接触C++,在尝试从 dll 中导出函数时,发现导出的函数名都"乱码"了. 导出过程如下: 新建一个Win32项目: 新建的解决方案里有几个导出的示例: // 下列 ifdef ...
- Linux下gcc编译控制动态库导出函数小结
根据说明文档“How To Write Shared Libraries"介绍, 有四种方法: 1. 在方法声明定义时,加修饰:__attribute__((visibility(" ...
- dll 导出函数名的那些事
dll 导出函数名的那些事 关键字: VC++ DLL 导出函数 经常使用VC6的Dependency或者是Depends工具查看DLL导出函数的名字,会发现有DLL导出函数的名字有时大不相同,导 ...
- 【C】——动态库中函数的作用范围
如何生成动态库 net小伙 已经在此文中说明——[C]——如何生成静态库和动态库:接下来就要看看动态库中函数的作用范围: 首先我们使用命令 gcc -fPIC -shared -o libtest ...
- C++ 编写的DLL导出的函数名乱码含义解析
C++编译时函数名修饰约定规则: __stdcall调用约定: 1.以"?"标识函数名的开始,后跟函数名: 2.函数名后面以"@@YG"标识参数表的 ...
- GCC制作动态库导出符号表【转】
转自:https://blog.csdn.net/whb_fei/article/details/76974543 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.cs ...
- MinGW g++.exe 编译 DLL 时,导出函数名带@的问题
今天尝试用CodeBlocks写了一个简单的Dll,发现生成的 dll 文件导出的函数名后面都有一个 @xxx 从生成的 libDll2.def 中看到: EXPORTS DllMain@ @ Max ...
- windows 动态库导出
以下内容来自博客:https://blog.csdn.net/fengbingchun/article/details/78825004 __declspec是Microsoft VC中专用的关键字, ...
- GCC链接库的一个坑:动态库存在却提示未定义动态库的函数
背景 在GCC中已经指定链接库,然而编译时却提示动态库函数未定义! 测试出现的错误提示如下: [GMPY@13:48 tmp]$gcc -o test -L. -lmylib test.c /tmp/ ...
随机推荐
- 通信网Project之——单源单宿最短路问题
最主要的Vertex类: #ifndef VERTEX_H #define VERTEX_H #include <climits> #include <cstddef> #de ...
- java 集装箱 arraylist 用法
1. ArrayList概述: ArrayList 是一个数组队列.相当于 动态数组. 与Java中的数组相比.它的容量能动态增长.它继承于AbstractList.实现了List, RandomAc ...
- 勾选Create git respository的作用
在Xcode中创建项目时会弹出Source Control选项,勾选Create git repository选项可以帮助我们对照以前项目中代码中修改的部分,为开发提供方便. 在项目完成到一定程度时, ...
- Coreseek:索引和检测的第二步骤施工
1,非常索引easy,代码行 g:/service/coreseek/bin/indexer -c g:/service/coreseek/etc/csft_mysql.conf person 在 ...
- java环境变量配置四种方法
原文:java环境变量配置四种方法 Java编程首要工作就是安装JDK(Java Development Kit).一通“NEXT”点完安装后就是最重要的环境变量设置了.也许有人会问为什么要设置环境变 ...
- 模板专业化和模板偏特样片(template specialization and partial template specialization)
测试环境: win7 64 g++ 4.8.1 /*************************************************************************** ...
- SQL点滴7—使用SQL Server的attach功能出现错误及解决方法
原文:SQL点滴7-使用SQL Server的attach功能出现错误及解决方法 今天用SQL Server 2008的attach功能附加一个数据库,出了点问题,提示的错误是: Unable to ...
- windows下oracle数据库定时备份与压缩批处理脚本(win7/win2008亲测通过)
第一种方式:全备份,并直接覆盖原来的备份文件,固定命名. 脚本: @echo off exp system/a123@HZPG file=e:\db_backup\oradata.dmp log=e: ...
- lua及luci学习
由于项目需要对Luci进行修改,所以这里开始地luci进行较深入的研究. 探索其中的运行路径. Openwrt默认的HTTP服务器为uhttpd,该WEB服务器是由Luci的开发者自行开发的,非常小巧 ...
- [LeetCode] ZigZag Conversion [9]
称号 The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows li ...