gpt4 book ai didi

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

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 34 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章详解C++ 动态库导出函数名乱码及解决由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

刚接触C++,在尝试从 dll 中导出函数时,发现导出的函数名都“乱码”了.

导出过程如下:

新建一个Win32项目:

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

新建的解决方案里有几个导出的示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 下列 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#里导入看看能否调用,嗯……错误来了:

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

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

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

Oh, shit, WTF is this? 导出是导出了,不过怎么都乱码了?

右键选择“Undecorate C++ Functions”之后才出现了真面目:

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

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

详解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"”就行了!”,我们来试试:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 下列 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# 项目:

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

没有指定 EntryPoint 了,成功! 。

以上所述是小编给大家介绍的C++ 动态库导出函数名乱码及解决详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我网站的支持! 。

原文链接:https://blog.csdn.net/LUOCHENLONG/article/details/85983182 。

最后此篇关于详解C++ 动态库导出函数名乱码及解决的文章就讲到这里了,如果你想了解更多关于详解C++ 动态库导出函数名乱码及解决的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com