• 自定义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模式输出

    调用正常

  • 相关阅读:
    SNMP、rrdtool
    mysqldump命令备份数据
    Ansible之playbook&&roles
    敏捷软件开发 原则、模式与实践 第9章的例子程序(C#版)
    iis websocket
    EDM 邮件营销 html&css编写建议和规范整理
    Microsoft .NET Framework
    线程上下文切换
    系统调用 用户态 内核态
    文件系统
  • 原文地址:https://www.cnblogs.com/apache11/p/7676953.html
Copyright © 2020-2023  润新知