访问dll的方法有很多,我列的这一种是个人认为比较容易理解和实现的,就是使用QPluginLoader来访问dll。
整理来自: http://qimo601.iteye.com/blog/1402501文件结构如下图:
解决方案名:TestPlugin
1、Qt的Library项目(PluginDll):PlugInterface.h、PluginInstance.h、PluginInstance.cpp
2、Qt的ConsoleApplication项目(PluginConsole):main.cpp、PlugInterface.h(从上面的项目拷贝过来的)
程序建立步骤
步骤一、在VS里新建立一个DLL项目,名称PluginDll。
-
把自动生成的三个代码文件(PluginDll.h、PluginDll_global.h、PluginDll.cpp)直接删掉,这三个是Qt自己的建立QtDll的推荐方法,我们暂时用不到。 -
自己新建如下三个文件PlugInterface.h、PluginInstance.h、PluginInstance.cpp
备注:如果步骤一建立成一个exe应用项目,也可以通过改两个项目配置参数实现,生成DLL。
一是修改Configuration Properties/General/Configurationtype的值,将Application (.exe)改成Dynamic Library(.dll),
二是修改Configuration Properties/Linker/General/Output File的值,将$(OutDir)\$(ProjectName).exe改成$(OutDir)\$(ProjectName).dll
PlugInterface.h代码
- //
PlugInterface.h - //接口类
- #ifndef
PLUGINTERFACE_H - #define
PLUGINTERFACE_H -
- #include
- class
PlugInterface - {
- public:
-
virtual ~PlugInterface(){} -
//接口中的成员函数必须是纯虚函数 -
virtual void testPlugin() = 0; -
virtual void helloWorld() = 0; - };
- QT_BEGIN_NAMESPACE
- //这个宏用声明接口
- //Q_DECLARE_INTERFACE(接口类名,接口标识符)
- Q_DECLARE_INTERFACE(PlugInterface,
"PlugInterfaceDll/1.0"); - QT_END_NAMESPACE
- #endif
// PLUGINTERFACE_H -
- //接口标识符必须唯一,所以一般加个版本号1.
- //This
macro is normally used right after the class definition for ClassName, in a header file. - //If
you want to use Q_DECLARE_INTERFACE with interface classes declared in a namespace, - //then
you have to make sure the Q_DECLARE_INTERFACE is not inside a namespace though.
PluginInstance.h代码
- //
PluginInstance.h - //业务类的头文件
- #ifndef
PLUGININSTANCE_H - #define
PLUGININSTANCE_H -
- #include
"PlugInterface.h" - #include
- //PluginInstance必须继承QObject类,才能使用如下Qt的方法
- //PluginInstance还得继承接口PlugInterface
- class
PluginInstance : public QObject, PlugInterface - {
-
Q_OBJECT -
//Q_INTERFACES宏定义告诉Qt MOC,PluginInstance类继承了插件PlugInterface -
//将该接口注册到Qt的meta-object system -
Q_INTERFACES(PlugInterface) - public:
-
PluginInstance(); -
~PluginInstance(); -
//业务成员1 -
void testPlugin(); -
//业务成员2 -
void helloWorld(); - };
-
- #endif
// PLUGININSTANCE_H
PluginInstance.cpp代码
- //
PluginInstance.cpp - //业务类成员函数定义
- #include
"PluginInstance.h" - #include
- PluginInstance::PluginInstance()
- {
- }
- PluginInstance::~PluginInstance()
- {
- }
- void
PluginInstance::testPlugin() - {
-
qDebug() << "test"; - }
- void
PluginInstance::helloWorld() - {
-
qDebug() << "helloWorld"; - }
- //这个宏用来导出动态链接库
- //Q_EXPORT_PLUGIN2(插件名,
类名) - //Q_EXPORT_PLUGIN2("PluginDll",
PluginInstance) - Q_EXPORT_PLUGIN2("PluginInstance",
PluginInstance) - //插件名最好和TARGET有关,而我们PluginDll项目转换成Qt项目的.pro文件,target
= PluginDll - //所以说这里名字不影响编程,只是为了方便理解,让插件名和项目名一致最好。
- //对于一个Qt插件来说,最好只有一个Q_EXPORT_PLUGIN2宏定义,并且最好在实现的文件里出现,而非头文件中。
步骤二、在VS里新建立一个ApplicationL项目,名称PluginConsole。
-
将前面PluginDll项目中的接口头文件PlugInterface.h拷贝到PluginConsole项目中; -
因为plugin.dll已经在解决方案的Debug文件中了,暂时就不需要拷贝到PluginConsole项目中来了。如果没有需要拷贝过来才能引用
在main.cpp中通过QPluginLoader调用PluginDll.dll
main.cpp代码
- #include
- #include
"PlugInterface.h" - #include
- #include
- int
main(int argc, char *argv[]) - {
-
QCoreApplication a(argc, argv); -
PlugInterface *plugObject; -
//不知道为啥,路径我写成下面就出错呢?编译可以通过,运行时会提示异常 -
//QPluginLoader pluginLoader("PluginDll.dll"); -
//加载插件 -
QPluginLoader pluginLoader("../Debug/PluginDll.dll"); -
// -
QObject *plugin = pluginLoader.instance(); -
if (plugin) -
{ -
qDebug() << "instance success"; -
//使用qobject_cast将QObject类型转换成我们想要的PlugInterface类对象 -
plugObject= qobject_cast(plugin); -
plugObject->helloWorld(); -
plugObject->testPlugin(); -
} -
else -
qDebug() << "instance fail"; -
return a.exec(); - }
注意:.dll文件要放到跟源程序一块的路径下,不然不会显示"instance fail"。这点请注意,之前我的程序老是显示失败,找了好久才注意到原因在这里。
本人亲测,运行结果如图:
希望我整理的文章能对你有所帮助,至少我是收获了很多,谢谢!