【转】http://blog.csdn.net/beanjoy/article/details/9136127

所谓名字修饰约定,就是指变量名、函数名等经过编译后重新输出名称的规则。

  比如源代码中函数名称为int Func(int a,int b),经过编译后名称可能为?Func@@YAHHH@Z、?Func@@YGHHH@Z、_Func@8,也有可能与源代码中名称相同为Func。

  影响编译后输出的名称通常与名字修饰约定(extern "C"、extern "C++"等)和函数调用约定(__stdcall、__cdecl等)等相关。

  口说千遍,不如实际演练一遍。那么,就让我们写代码来测试下。

  注意,本文只讨论extern "C"、extern "C++"和__stdcall、__cdecl相关的约定,其他约定不在本文讨论范围内。另外,编译的环境为XP + VC++6.0SP6。

  首先,用C方式导出两个函数:

  Dll1.c

  1. _declspec(dllexport) int __cdecl Func_cdecl(int a,int b)
  2. {
  3. return 1;
  4. }
  5. _declspec(dllexport) int __stdcall Func_stdcall(int a,int b)
  6. {
  7. return 1;
  8. }

  导出的两个函数名为:

  再以C++方式导出:

  Dll1.cpp

  1. _declspec(dllexport) int __cdecl Func_cdecl(int a,int b)
  2. {
  3. return 1;
  4. }
  5. _declspec(dllexport) int __stdcall Func_stdcall(int a,int b)
  6. {
  7. return 1;
  8. }

  导出结果如下:

  然后,我们再以C++方式导出如下代码中的函数:

  1. extern "C" _declspec(dllexport) int __stdcall Func_C_stdcall(int a,int b)
  2. {
  3. return 1;
  4. }
  5. extern "C++" _declspec(dllexport) int __stdcall Func_CPP_stdcall(int a,int b)
  6. {
  7. return 1;
  8. }
  9. extern "C" _declspec(dllexport) int __cdecl Func_C_cdecl(int a,int b)
  10. {
  11. return 1;
  12. }
  13. extern "C++" _declspec(dllexport) int __cdecl Func_CPP_cdecl(int a,int b)
  14. {
  15. return 1;
  16. }

  导出结果如下:

  有了以上实验结果,我们再结合以下名字输出规则进行理解:

  1. C方式编译(extern "C"):
    1. __stdcall调用约定:输出名称在原名称前加一下划线,后面再加上一个“@”和其参数的总字节数(_原名称@参数总字节数),如名称int Func_C_stdcall(int a,int b)输出为_Func_C_stdcall@8;
    2. __cdecl调用约定:与原名称相同,如名称int Func_C_cdecl(int a,int b)输出还是为Func_C_cdecl;
  2. C++方式编译(extern "C++"):
    1. __stdcall调用约定:
      1. 输出名称以“?”开始,后跟原名称;
      2. 原名称后再跟“@@YG”,后面再跟返回值代号和参数表代号,代号表示如下:
        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”代表一次重复;
      3. 参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。如名称int Func_CPP_stdcall(int a,int b)编译后的输出名称为?Func_CPP_stdcall@@YGHHH@Z。
    2. __cdecl调用约定:与_stdcall调用约定基本一致,只是参数表的开始标识由上面的“@@YG”变为“@@YA”。如名称int Func_CPP_cdecl(int a,int b)编译后输出名称为?Func_CPP_cdecl@@YAHHH@Z。

  

  有个这个规则,再回头去看我们的实验结果,就很好理解了。

  当然,编译C文件和编译CPP文件,不需加extern "C"和extern "C++",因为编译C文件当然默认的是extern "C",而编译CPP文件则默认的是extern "C++"。

  现在我们也能理解为什么导出DLL时通常需要加上extern "C"。试想,如果一个C++导出的dll,没有加extern "C",则导出的名称为extern "C++"约定下的名称。如果这个dll需要提供给用C编写的程序使用,那么这个程序是无法调用这个dll的,因为C写的程序遵循的是extern "C"约定,链接时链接器将按照extern "C"约定的名称去寻找外部名称,这当然找不到,因为dll中的输出名称为extern "C++"约定下的名称。

dll函数生成规则的更多相关文章

  1. [转载]DLL命名规则

    程序集是一个部署单元,同时还代表托管代码程序的身份.一般来说一个程序集仅与一个DLL相对应.本节主要讲DLL命名约定,程序集的命名约定与此类似. 要记住,名字空间与DLL和程序集是不同的概念.名字空间 ...

  2. MFC的规则DLL与扩展DLL

    一.MFC规则DLL     MFC规则DLL可以在该dll内部使用MFC,但是与应用程序的接口不能是MFC的.能够被所有支持dll的编程语言所写的应用程序使用,当然也包括使用MFC创建的应用程序.在 ...

  3. VC++动态链接库(DLL)编程深入浅出(zz)

    VC++动态链接库(DLL)编程深入浅出(zz) 1.概论 先来阐述一下DLL(Dynamic Linkable Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用 ...

  4. VS2010 C++环境下DLL和LIB文件目录及名称修改

    VS2010 C++环境下DLL和LIB文件目录及名称修改 转自:http://blog.csdn.net/archielau/article/details/8507581 DLL工程,Debug版 ...

  5. AFX_MANAGE_STATE(AfxGetStaticModuleState())DLL导出函数包含MFC资源

    AFX_MANAGE_STATE(AfxGetStaticModuleState()) 先看一个例子: .创建一个动态链接到MFC DLL的规则DLL,其内部包含一个对话框资源.指定该对话框ID如下: ...

  6. VC++制作DLL详解

    1.    DLL的基本概念 应用程序(exe)要引用目标代码(.obj)外部的函数时,有两种实现途径——静态链接和动态链接. 1.    静态链接 链接程序搜索对应的库文件(.lib),然后将这个对 ...

  7. VC++制作DLL具体解释

    1.    DLL的基本概念 应用程序(exe)要引用目标代码(.obj)外部的函数时,有两种实现途径--静态链接和动态链接. 1.    静态链接 链接程序搜索相应的库文件(.lib),然后将这个对 ...

  8. VC中不同类型DLL及区别

    1. DLL的概念可以向程序提供一些函数.变量或类. 静态链接库与动态链接库的区别:(1)静态链接库与动态链接库都是共享代码的方式.静态链接库把最后的指令都包含在最终生成的EXE文件中了:动态链接库不 ...

  9. dll的概念 dll导出变量 函数 类

    1. DLL的概念 DLL(Dynamic Linkable Library),动态链接库,可以向程序提供一些函数.变量或类.这些可以直接拿来使用. 静态链接库与动态链接库的区别:   (1)静态链接 ...

随机推荐

  1. celery制作定时任务

    celery参考地址:http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html#starting-the-schedu ...

  2. 在 myeclipse中进行连接sql server的测试

    在 myeclipse中,连接 sql server 用的 url connection 与 java 代码 连接的 url值完全相同. (一下为 java的jdbc连接 sql server 成功的 ...

  3. Oracle合并某一列

    本文转载自:https://www.cnblogs.com/LeiYang5237/p/6761183.html 一.oracle11g使用listagg() within group()函数 如图一 ...

  4. idea maven 打包 引用本地jar

    1将本地jar包导入到mvn本地库 mvn install:install-file -Dfile=/Users/liuqiang/Documents/gmpl/gmpl-server/lib/ali ...

  5. CentOS7 php7 安装 curl 扩展

    直接从php源码包中,使用root权限安装. 找到原先安装PHP的源码包文件(如果已经删掉需要重新下载原来版本的源码包并解压) 我的php源码包在root家目录下. cd /php-7.1.4/ext ...

  6. SQL 只取重复记录一条记录并且是最小值

    and not exists( and a.StateValue>StateValue ) '

  7. Tomcat常用设置

    远程Dbug调试: TOMCAT配置(只需设置一次): 1.在服务器的$TOMCAT_HOME/bin/catalina.sh中增加: CATALINA_OPTS="-server -Xde ...

  8. PDA后台运行、安装程序

    ////启动最新版本安装(后台安装模式),结束更新程序            //string cabPath = @"\Application Data\QY.DDM.PDA.CAB&qu ...

  9. 设计模式-访问者(Visitor)模式

    访问者模式是对象的行为模式.访问者模式的目的是封装施加在某种数据结构元素上的操作.一旦一些操作需要修改,接受这个操作的数据结构可以保持不变. 个人觉得访问者模式相对其他的设计模式来说稍微复杂,难理解一 ...

  10. OSGi学习-总结

    本文是osgi实战一书的前几章读书总结 1.  OSGi简介 Java缺少对高级模块化的支持,为了弥补Java在模块化方面的不足,大多数管理得当的项目都会要求建立一整套技术,包括: 适应逻辑结构的编程 ...