zoukankan      html  css  js  c++  java
  • DLL入门浅析(4)——从DLL中导出类

    转载自:http://www.cppblog.com/suiaiguo/archive/2009/07/20/90663.html

    前面介绍了怎么从DLL中导出函数和变量,实际上导出类的方法也是大同小异,废话就不多说了,下面给个简单例子示范一下,也就不多做解释了。

    DLL头文件:

    #ifndef _DLL_SAMPLE_H
    #define _DLL_SAMPLE_H
    
    // 通过宏来控制是导入还是导出
    #ifdef _DLL_SAMPLE
    #define DLL_SAMPLE_API __declspec(dllexport)
    #else
    #define DLL_SAMPLE_API __declspec(dllimport)
    #endif
    
    // 导出/导入变量声明
    DLL_SAMPLE_API class DLLClass
    {
      public:
        void Show();
    };
    
    #undef DLL_SAMPLE_API
    
    #endif
    View Code

    DLL实现文件:

    #include "stdafx.h"
    #define _DLL_SAMPLE
    
    #ifndef _DLL_SAMPLE_H
    #include "DLLSample.h"
    #endif
    
    #include "stdio.h"
    
    //APIENTRY声明DLL函数入口点
    BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
    {
     switch (ul_reason_for_call)
     {
      case DLL_PROCESS_ATTACH:
      case DLL_THREAD_ATTACH:
      case DLL_THREAD_DETACH:
      case DLL_PROCESS_DETACH:
       break;
     }
     return TRUE;
    }
    
    void DLLClass::Show()
    {
      printf("DLLClass show!");
    }
    View Code

    应用程序调用DLL

    #include "DLLSample.h"
    
    #pragma comment(lib,"DLLSample.lib")
    
    
    int main(int argc, char *argv[])
    {
     DLLClass dc;
      dc.Show();
     return 0;
    }
    View Code

    大家可能发现了,上面我没有使用模块定义文件(.def)声明导出类也没有用显式链接导入DLL。
    用Depends查看前面编译出来的DLL文件,会发现里面导出了很奇怪的symbol,这是因为C++编译器在编译时会对symbol进行修饰。 这是我从别人那儿转来的截图。

    网上找了下,发现了C++编译时函数名的修饰约定规则

    __stdcall调用约定:

    1、以"?"标识函数名的开始,后跟函数名; 2、函数名后面以"@@YG"标识参数表的开始,后跟参数表; 3、参数表以代号表示:

    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"代表一次重复; 4、参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前;
    5、参数表后以"@Z"标识整个名字的结束,如果该函数无参数,则以"Z"标识结束。   其格式为"?functionname@@YG*****@Z"或?functionname@@YG*XZ

        int Test1(char *var1,unsigned long)-----“?Test1@@YGHPADK@Z”
         void Test2()                          -----“?Test2@@YGXXZ”
    

    __cdecl调用约定:   规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YA"。

    __fastcall调用约定:   规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YI"。
    VC++对函数的省缺声明是"__cedcl",将只能被C/C++调用。
    虽然因为C++编译器对symbol进行修饰的原因不能直接用def文件声明导出类和显式链接,但是可以用另外一种取巧的方式。

    在头文件中类的声明中添加一个友元函数: friend DLLClass* CreatDLLClass(); 然后声明CreatDLLClass()为导出函数,通过调用该函数返回一个DLLClass类的对象,同样达到了导出类的目的。 这样,就可以用显式链接来调用CreatDLLClass(),从而得到类对象了。

    ——现在的努力是为了小时候吹过的牛B!!
  • 相关阅读:
    poj3278 Catch That Cow
    poj2251 Dungeon Master
    poj1321 棋盘问题
    poj3083 Children of the Candy Cor
    jvm基础知识—垃圾回收机制
    jvm基础知识1
    java面试基础必备
    java soket通信总结 bio nio aio的区别和总结
    java scoket aIO 通信
    java scoket Blocking 阻塞IO socket通信四
  • 原文地址:https://www.cnblogs.com/pingge/p/3315754.html
Copyright © 2011-2022 走看看