以前的关于动态链接库的写法多是直接采用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 de scription
*/
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;
}