原文地址: https://stackoverflow.com/questions/26234327/qlibrary-import-a-class
c++ 的类中方法定位是编译时就完成的,而不是在run-time时去定位,所以动态加载时无法直接通过类名::函数名的方式调用到类中的方法。
但是这里有一种使用非常广泛的方式。
可以对要导出的类添加一个接口类,做成独立的文件并向外公开(只要将“interface”.h 头文件公开就行,不需要将工程中的源代码或其他头文件公开 )。对可能要对外公开的函数和功能都在接口类中做成虚函数。这样通过虚表的方式使其可以在run-time 时进行定位。
再对类添加创建对象函数,返回类型为接口类类型,并通过c语言函数导出。
第三方调用时,将接口类文件添加到对方工程中,而实际的功能代码和头文件不暴露出去(也就是不需要暴露你继承接口函数的类名),可以对代码起到一定的保护作用 。用创对象函数创建对象,然后就可以进行使用了。
对于类中的静态方法,可以单独提取出来,做成C语言函数。
示例
“interface.h”(接口文件。要对外开放)
class Interface
{
public: virtual void fun3() =0;
}
“interface1.h”(接口文件。要对外开放)
class Interface1
{
public: virtual int fun1(){ return 1; }
}
//除接口文件外,其他文件都不对外开放。假设要生成的dll名字为Base.dll
“defines.h"(不对外开放)(要求在生成dll的工程的工程配置中 配置属性->c/c++->预处理器->预处理器定义 值的 前面或后面 加上 “TEMPDLLEXPORT;”)
#ifdef TEMPDLLEXPORT
#define DLLUSAGE __declspec(dllexport)
#else
#define DLLUSAGE __declspec(dllimport)
#endif
“base.h”
#include "interface.h"
DLLUSAGE
#include "interface1.h"
class Base:public interface,public interface1
{
public:
virtual void fun3();
};
“base.cpp”
#include "base.h"
#include "defines.h"
class DLLUSAGE Base :public BaseInterface
{
virtual int fun1() override
{
return 10;
}
virtual void fun3() override
{
printf("gogog\n");
}
};
extern "C" DLLUSAGE Interface* getBaseObject()
{
return new Base();
}
第三方客户端:(像这里的getprocAddress提供者其实可以在做一次封装,用静态库来代替再提供给客户使用。那么对于动态加载只要通过销毁对象重新创建对象就行。以后有新的功能更改,也只需要更换动态库就行)
"main.h"
#include"interface.h"
#include<Windows.h>
typedef Interface* (*MYFUNC)();
int main(int argc, char *argv[])
{
HANDLE hDll; //void *
hDll = LoadLibrary("Base.dll"); //导入动态链接库
MYFUNC myFunc = (MYFUNC)GetProcAddress(hDll, "getBaseObject");//proc程序
Interface* baseObj = myFunc();
system("pause");
return 0;
}
__declspec 参考:https://www.cnblogs.com/jueyunqi/p/4140141.html