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++dllExport导出乱码

C++ 动态库导出函数名“乱码”及解决的更多相关文章

  1. 【图文】[新手]C++ 动态库导出函数名“乱码”及解决

    刚接触C++,在尝试从 dll 中导出函数时,发现导出的函数名都"乱码"了. 导出过程如下: 新建一个Win32项目: 新建的解决方案里有几个导出的示例: // 下列 ifdef ...

  2. Linux下gcc编译控制动态库导出函数小结

    根据说明文档“How To Write Shared Libraries"介绍, 有四种方法: 1. 在方法声明定义时,加修饰:__attribute__((visibility(" ...

  3. dll 导出函数名的那些事

    dll 导出函数名的那些事 关键字: VC++  DLL  导出函数 经常使用VC6的Dependency或者是Depends工具查看DLL导出函数的名字,会发现有DLL导出函数的名字有时大不相同,导 ...

  4. 【C】——动态库中函数的作用范围

    如何生成动态库 net小伙 已经在此文中说明——[C]——如何生成静态库和动态库:接下来就要看看动态库中函数的作用范围: 首先我们使用命令   gcc -fPIC -shared -o libtest ...

  5. C++ 编写的DLL导出的函数名乱码含义解析

    C++编译时函数名修饰约定规则: __stdcall调用约定:   1.以"?"标识函数名的开始,后跟函数名:     2.函数名后面以"@@YG"标识参数表的 ...

  6. GCC制作动态库导出符号表【转】

    转自:https://blog.csdn.net/whb_fei/article/details/76974543 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.cs ...

  7. MinGW g++.exe 编译 DLL 时,导出函数名带@的问题

    今天尝试用CodeBlocks写了一个简单的Dll,发现生成的 dll 文件导出的函数名后面都有一个 @xxx 从生成的 libDll2.def 中看到: EXPORTS DllMain@ @ Max ...

  8. windows 动态库导出

    以下内容来自博客:https://blog.csdn.net/fengbingchun/article/details/78825004 __declspec是Microsoft VC中专用的关键字, ...

  9. GCC链接库的一个坑:动态库存在却提示未定义动态库的函数

    背景 在GCC中已经指定链接库,然而编译时却提示动态库函数未定义! 测试出现的错误提示如下: [GMPY@13:48 tmp]$gcc -o test -L. -lmylib test.c /tmp/ ...

随机推荐

  1. Cannot find ActionMappings or ActionFormBeans collection

    出现此问题.首先检查web.xml,的主要结构被认为是在下面的图: 再检查struts-config.xml.确认是否有<form-beans>和<action-mappings&g ...

  2. Qt5官方demo分析集29——Extending QML - Property Value Source Example

    此系列的所有文章都可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集28--Extend ...

  3. 针对不同手机系统的LBS地图定位解决方案

    原文:针对不同手机系统的LBS地图定位解决方案 摘要: 针对目前的三种手机系统:Android安卓.S60塞班.IOS苹果,做出的三种不同的手机地图应用解决方案. 查阅了多数地图API对手机的支持情况 ...

  4. java语言内部类和匿名内部类

    内部类 在类定义也有类,在该类上的内部被称为一个内部类. 访问功能: 1,内部类可以直接访问外部类成员,它包含私有成员 2,外部类需要访问内部类的成员将需要建立一流的内部对象. 一般用于类的设计. 分 ...

  5. 用Iconv应对NodeJs对称加密技术在汉字编码与NoSQL的一些坑洞

    ·起因 汉字编码技术在实际应用中总是会存在这样或者那样的问题,尤其是在一些热门NoSQL方面多少会遇到挑战.比方说Cassandra字符集还不直接支持GB2312,要想存储写汉字那可真是麻烦.当然这还 ...

  6. C语言库函数大全及应用实例三

    原文:C语言库函数大全及应用实例三 [编程资料]C语言库函数大全及应用实例三 函数名: ecvt 功 能: 把一个浮点数转换为字符串 用 法: char ecvt(double value, int ...

  7. 学习Swift写iOS?那写安卓和WinPhone呢?请看一石三鸟终极解决方案 - Silver!

    首先,你必须知道的是,Silver是苹果最新编程语言Swift的免费实现版本. 通过Silver,你可以使用Swift语言来编写.NET,Java,安卓和Cocoa APIs.你甚至可以在这些平台上共 ...

  8. sql点滴42—mysql中的数据结构

    原文:sql点滴42-mysql中的数据结构 MySQL 的数值数据类型可以大致划分为两个类别,一个是整数,另一个是浮点数或小数.许多不同的子类型对这些类别中的每一个都是可用的,每个子类型支持不同大小 ...

  9. 设计模式之职责链模式(Chain of Responsibility)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  10. AR9331中Linux内核启动中与IRQ中断相关的文件

    先列出框架,具体后继再来分析. 首先是lds文件,该文件设置了各个section在FLASH或RAM中的先后顺序. 位于~/openwrt1407/build_dir/target-mips_34kc ...