动态链接库中使用c++类的方法

时间:2022-01-04 15:48:32
以前的关于动态链接库的写法多是直接采用extern 'C'的方式来实现,但是如果采用类来编写就会出现问题了,因为类在编译时是不能确定入口点位置的。这样就产生了问题。怎么来使用呢?前两个方法是在linux下直接使用普通函数调用的方法来实现的。后边的是在vc++中使用宏来对入口点动态调整输入输出__declspec(dllimport)和__declspec(dllexport)
  方法1:   把类作为参数传入   接口函数中去:  
  //-----------------------   myclass.h   文件-----------------    
  #ifndef   MYCLASS_H  
  #define   MYCLASS_H  
   
  class   myclass  
  {  
      public:  
          myclass(){}  
          ~myclass()   {}  
   
      public:  
          int   sum(int   a,int   b);  
       
      private:  
          int   _a;  
          int   _b;  
  };  
   
  #ifdef     SHARED  
  int           (*sum)(myclass   *my,int   a,int   b);  
  #else  
  int           sum(myclass   *my,int   a,int   b);  
  #endif  
   
  #endif   //   MYCLASS_H  
   
  //-----------------------   myclass.cpp   文件-----------------    
  #include   "myclass.h"    
   
  int   myclass::sum(int   a,int   b)  
  {  
      int   c   =   a   +   b;  
      return   c;  
  }  
   
  int     sum(myclass   *my,int   a,int   b)  
  {  
    int   c   =   my->sum(a,b);  
    return   c;  
  }  
   
  //-----------------------   my.cpp   测试文件   文件-----------------    
  #include   <iostream>  
  #include <dlfcn.h>  
  #define   SOFILE "./my.so"  
   
  #define SHARED  
  #include "myclass.h"  
   
  using   namespace   std;  
   
  int   main(int   argc,   char   *argv[])  
  {  
      myclass   my;  
      void   *dp;  
      char   *error;  
       
    cout<<"动态链接库应用示范"<<endl;  
     
    dp=dlopen(SOFILE,RTLD_LAZY); /*   打开动态链接库   */  
   
    if   (dp==0) /*   若打开失败则退出   */  
    {  
      cout<<"若打开失败则退出     dlopen"<<endl;    
      return(1);  
    }  
     
    sum=(int(*)(myclass   *my,int   a,int   b))dlsym(dp,"sum"); /*   定位求和函数   */  
   
    error=dlerror(); /*   检测错误   */  
    if   (error) /*   若出错则退出   */  
    {  
      cout<<"若出错则退出   :定位求和函数   sum"<<endl;  
      return(1);  
    }  
   
      int   a   =   10;  
      int   b   =   100;  
      int   c   =   sum(&my,a,b); /*   调用此共享函数   */  
      cout<<"c   =   "<<endl;  
      system("PAUSE");  
      return   0;  
  }  
   
  编译:  
  g++   myclass.h   myclass.cpp   -shared   -o   my.so        
  g++   my.cpp   -rdynamic   -lds   -o   my.exe               

    
  **********************************************************************  
   
  方法2:   声名一个类的全局变量   然后在接口中使用这个全局变量:  
   
  //-----------------------   myclass.h   文件-----------------    
  #ifndef   MYCLASS_H  
  #define   MYCLASS_H  
   
  /*  
    *   No   description  
    */  
  class   myclass  
  {  
      public:  
          myclass(){}  
          ~myclass()   {}  
   
      public:  
          int   sum(int   a,int   b);  
       
      private:  
          int   _a;  
          int   _b;  
  };  
   
  //声名一个类的全局变量   然后在接口中使用这个全局变量:  
  extern     myclass   my;  
   
  #ifdef     SHARED  
  int           (*sum)(int   a,int   b);  
  #else  
  int           sum(int   a,int   b);  
  #endif  
   
  #endif   //   MYCLASS_H  
   
  //-----------------------   myclass.cpp   文件-----------------    
  #include   "myclass.h"    
   
  int   myclass::sum(int   a,int   b)  
  {  
      int   c   =   a   +   b;  
      return   c;  
  }  
   
  int     sum(int   a,int   b)  
  {  
    int   c   =   my.sum(a,b);  
    return   c;  
  }  
   
  //-----------------------   my.cpp   测试文件   文件-----------------    
  #include   <iostream>  
  #include <dlfcn.h>  
  #define   SOFILE "./my.so"  
  #define SHARED  
  #include "myclass.h"  
   
  using   namespace   std;  
   
  int   main(int   argc,   char   *argv[])  
  {  
      //myclass   my;  
      void   *dp;  
      char   *error;  
       
    cout<<"动态链接库应用示范"<<endl;  
     
    dp=dlopen(SOFILE,RTLD_LAZY); /*   打开动态链接库   */  
   
    if   (dp==0) /*   若打开失败则退出   */  
    {  
      cout<<"若打开失败则退出     dlopen"<<endl;    
      return(1);  
    }  
     
    sum=(int(*)(int   a,int   b))dlsym(dp,"sum"); /*   定位求和函数   */  
   
    error=dlerror(); /*   检测错误   */  
    if   (error) /*   若出错则退出   */  
    {  
      cout<<"若出错则退出   :定位求和函数   sum"<<endl;  
      return(1);  
    }  
   
      int   a   =   10;  
      int   b   =   100;  
      int   c   =   sum(a,b); /*   调用此共享函数   */  
      cout<<"c   =   "<<endl;  
      system("PAUSE");  
      return   0;  
  }   
    
  编译:  
  g++   myclass.h   myclass.cpp   -shared   -o   my.so 
  g++   my.cpp   -rdynamic   -lds   -o   my.exe    *************************************************************   方法三:    在 DLL 的输出头文件中用上: #ifdef MYLIBAPI #else   #define MYLIBAPI __declspec(dllimport) #endif 在 DLL 的 cpp 文件中,引用头文件的前面加上: #define MYLIBAPI __declspec(dllexport)   注意,这时候 extern “C” 已经没有了。因为我们要输出的就是 C++ 类。 同时,在类的头文件中,类的定于前面写上: class MYLIBAPI classname { } 这就 OK 啦。   *************************************************        #include <iostream>

using namespace std;

class DLLClass{
        public:
                // exported member function
                __declspec(dllexport) void functionA(void)
                {
                        cout << "In Function A of the exported function" << endl;
                        return;
                }
};

// exported class
class __declspec(dllexport) ExportDLLClass{
        public:
                void functionB(void)
                {
                        cout << "In Function B of the exported class" << endl;
                        return;
                }
};

// exported instance of the DLLClass
__declspec(dllexport) DLLClass test;
保存成TestDLL.cpp然后进行编译。呵呵,因为是用Editplus写的代码,所以要手动编译哦^^
我用的是VS 2005的CL编译接口CL.exe。在Cmd下:CL/c TestDLL.cpp
此时就生成了TestDLL.obj,然后进行链接:link TestDLL.obj /DLL
此时将生成TestDLL.dll,TestDll.exp,TestDll.lib三个文件
工作暂告一个段落。。。。

然后开始写调用TestDLL.dll的CallDLL.exe文件:
 class DLLClass{
        public:
                // imported member function
        __declspec(dllimport) void functionA(void);
};

// imported class
class __declspec(dllimport) ExportDLLClass{
        public:
                void functionB(void);
};

// imported instance of the DLLClass
__declspec(dllimport) DLLClass test;

int main(void)
{
        ExportDLLClass TestClass;
                     test.functionA();
                     TestClass.functionB();
        return 0;
}