zoukankan      html  css  js  c++  java
  • 在DLL编程中,导出函数为什么需要extern "C"

     转自:http://blog.csdn.net/zhongjling/article/details/8088664

    一般来讲,在DLL编程过程中,对于导出的函数前 都需要加入 extern “C”, 

      extern 表示这是个全局函数,可以供各个其他的函数调用;

      “C” 表示编译时按照 C编译器的方式进行编译,而不是C++。 C++的编译方式考虑了函数重载,所以对函数名进行了新的修饰,产生了所谓的破坏性命名。

    不过,也有特殊情况,有三种例外情况可以不加extern   “C”: 
    1、如果不是用C++编译器而是用C编译DLL,名字不会变,可以不加extern   "C" 
    2、如果DLL的使用者知道是用C++编译器编译DLL,不加extern   “C”也可以,因为他知道名字改变的规则。调用GetProcAddress时,把函数名字改了就是了,改为修饰后的函数名。 如 fnDll1  改为 ?fnDll1@@YAHXZ。

    例子关键代码如下: 
    ---------------------------- 
    DLL部分: 
    //   This   is   an   example   of   an   exported   function. 
    DLL1_API   int   __cdecl   fnDll1(void) 

    return   42; 

    输出的修饰函数名为?fnDll1@@YAHXZ 

    DLL1_API   int   __cdecl   fnDll1(int   a) 

    return   42+a; 


    输出的修饰函数名为?fnDll1@@YAHH@Z 
    ----------------------------- 
    EXE部分: 
    HINSTANCE   hModule   =   LoadLibrary("dll1.dll"); 
    ASSERT(hModule); 
    typedef   int   (*fnDll1)(); 
    fnDll1   pfnDll1   =   NULL; 
    //VERIFY(pfnDll1   =   (fnDll1)::GetProcAddress(hModule,   "fnDll1")); 
    VERIFY(pfnDll1   =   (fnDll1)::GetProcAddress(hModule,   "?fnDll1@@YAHXZ")); 
    ASSERT(pfnDll1()   ==   42); 

    typedef   int   (*fnDll2)(int); 
    fnDll2   pfnDll2   =   NULL; 
    VERIFY(pfnDll2   =   (fnDll2)::GetProcAddress(hModule,   "?fnDll1@@YAHH@Z")); 
    ASSERT(pfnDll2(3)   ==   45); 
    --------------------------- 

    3.上面的2太麻烦了。所以还有一种方法是使用def文件。

     (如果DLL使用的是def文件,要删除TestDll.h文件中关键字extern "C",即2者是不能共存的)。

        def 文件(模板定义文件),第一个语句必须是 LIBRARY 语句,指出DLL的名字;

        EXPORTS语句 列出被导出函数的名字;将要输出的函数罗列出来,这个函数名字必须与定义函数的名字完全一致,如此既可以得到

        一个没有任何修饰符的函数名了。

       被导出的函数 可以和一个序号相对应。定义序号时必须在数字前加一个@。例如  isRUINIan  @1      //IsRuiNian 函数对应序号为 1

     

    这样的话,我们既可以GetProAddress(hinstance,“IsRuiNian”),也可以 GetProAddress(hinstance,(LPCSTR)1)实现调用。

      

    参考:http://topic.csdn.net/t/20021012/17/1090973.html

          http://www.qqgb.com/program/vc/vcjq/program_166495.html

    既然选择了远方,就不顾风雨兼程
  • 相关阅读:
    多线程(一)高并发和多线程的关系
    spring源码浅析——IOC
    网络爬虫(java)
    数据结构—平衡二叉树
    设计模式—抽象工厂模式
    设计模式—工厂方法模式
    scala(二) Future执行逻辑解读
    java异常处理机制
    为什么覆写equals必须要覆写hashCode?
    Scala对MongoDB的增删改查操作
  • 原文地址:https://www.cnblogs.com/zhengfa-af/p/8109240.html
Copyright © 2011-2022 走看看