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

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模式输出

 

 

调用正常

 

posted @ 2017-10-16 14:51  apache11  阅读(910)  评论(0编辑  收藏  举报