详解C++ 动态库导出函数名乱码及解决

 更新时间:2019年03月13日 14:34:46   作者:luochenlong  
这篇文章主要介绍了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@Z

                     void 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语言_构建一个静态二叉树实现方法

    下面小编就为大家带来一篇c语言_构建一个静态二叉树实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • C++ 11和C++98相比有哪些新特性

    C++ 11和C++98相比有哪些新特性

    C++11标准提供了许多有用的新特性。这篇文章特别针对使C++11和C++98相比看上去像一门新语言的特性
    2017-03-03
  • C++ STL反向迭代器的实现

    C++ STL反向迭代器的实现

    本文主要介绍了C++ STL反向迭代器的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 《C++ primer plus》读书笔记(二)

    《C++ primer plus》读书笔记(二)

    本读书笔记是读了《C++ primer plus(第六版)》第五至八章的学习笔记。是C++读书笔记系列的第二篇。复习C++基础知识的可以瞄瞄。
    2014-10-10
  • C++基础学习之利用两个栈实现一个队列

    C++基础学习之利用两个栈实现一个队列

    这篇文章主要给大家介绍了关于C++基础学习之利用两个栈实现一个队列的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用C++具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-05-05
  • Ubuntu中使用VS Code与安装C/C++插件的教程详解

    Ubuntu中使用VS Code与安装C/C++插件的教程详解

    这篇文章主要介绍了Ubuntu中使用VS Code与安装C/C++插件的教程详解,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • C++算术运算符与类型转换

    C++算术运算符与类型转换

    这篇文章主要介绍了C++算术运算符与类型转换,C++当中提供5种基础的算术运算符,分别是加法、减法、乘法、除法和取模。下main我们就一起来看看下面文章得具体举例与说明,需要的朋友可以参考一下,希望对你有所帮助
    2021-11-11
  • C语言趣味编程之水仙花数

    C语言趣味编程之水仙花数

    这篇文章介绍了C语言趣味编程之水仙花数,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-11-11
  • C++基于文件流与armadillo读取mnist示例详解

    C++基于文件流与armadillo读取mnist示例详解

    这篇文章主要给大家介绍了关于C++基于文件流与armadillo读取mnist的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • QT网络通信TCP客户端实现详解

    QT网络通信TCP客户端实现详解

    这篇文章主要为大家详细介绍了QT网络通信TCP客户端实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08

最新评论