以前的關於動態連結程式庫的寫法多是直接採用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;
}