您的位置:首页 > 编程语言 > C语言/C++

自定义C/C++ dll导出后函数名为乱码(如@func@@YGXHX@Z)原因以及解决方案

2017-10-16 14:51 302 查看
1,现象:

自定义C/C++ dll,编译无错误,另一程序使用动态调用方法,加载dll正常,但是调用函数时使用各种方法无法成功。

使用dll查看工具,发现函数名为func和乱码的组合,如下图:



2, 原因查找:

各方查找原因,发现原因并不是有的帖子说的要在编译dll的头文件中加入 extern "C"

extern "C"只是说明导出函数使用C编译器,不加extern "C"说明使用C++编译器规则。

两种规则区别如下:

(1)C编译器的函数名修饰规则

对于__stdcall调用约定,编译器和链接器会在输出函数名前加上一个下划线前缀,函数名后面加上一个“@”符号和其参数的字节数,如果原始函数为func(),编译后变为_func@;

(2)C++编译器的函数名修饰规则

C++的函数名修饰规则内容更加丰富,包含函数名,返回值类型,参数类型等信息。

a, 不管__cdecl,__fastcall还是__stdcall调用方式,函数修饰都是以一个“?”开始

b, 后面紧跟函数的名字

再后面是参数表的开始标识和按照参数类型代号拼出的参数表。

c, 详细规则如下:__stdcall,参数表的开始标识是“@@YG”

   __cdecl方式则是“@@YA”

       __fastcall方式则是“@@YI”。

d, 参数表以代号表示:
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"代表一次重复;
参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前;

e, 参数表后以"@Z"标识整个名字的结束,如果该函数无参数,则以"Z"标识结束。

extern "C"只解决了C和C++语方之间调用的问题(extern "C" 是告诉编译器,让它按C的方式编译),它只能用于导出全局函数这种情况 而不能导出一个类的成员函数。
同时如果导出函数的调用约定发生改变,即使使用extern "C",编译后的函数名还是会发生改变。

3. 正确方法

  添加模块定义文件(def文件):

LIBRARY "dodll"

EXPORTS
test1 @ 1
test2 @ 2

同时以release模式输出





调用正常
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: