上一章我们已经有了一个MonsterInterface
接口。现在,让我们使用这个接口来创建一个怪物插件 Troll(食人怪)。
首先还是要给出 Troll 的 pro 文件:
QT -= gui TARGET = Troll TEMPLATE = lib DEFINES += TROLL_LIBRARY DESTDIR = ../plugins MOC_DIR = troll OBJECTS_DIR = troll INCLUDEPATH += ../GameSystem SOURCES += troll.cpp HEADERS += troll.h\ Troll_global.h
下面我们来分析下这个文件。首先,我们的插件不需要 GUI 部分(因为前面说过,为简便起见,我们去除掉界面),所以会有QT -= gui
。TARGET 代表生成的插件的名字,这里就是 Troll。TEMPLATE 设置为 lib。只要是编写插件,我们的 TEMPLATE 就是 lib。DEFINES 代表在编译时添加的宏。这里我们引入一个宏TROLL_LIBRARY
,具体作用我们会在后文详细介绍。目的文件夹 DESTDIR 设置为 ../plugins。这里的 .. 是相对于编译输出目录,也就是说,我们需要在 Qt Creator 的 Project 的 Building Path 设置为 E:\Qt\game\build\troll(回忆下上一章,我们将 GameSystem 的构建目录设置为 E:\Qt\game\build\sys,这需要我们手动设置,以保证它们会生成在同一个目录下,而 GameSystem 的构建目录是 build/sys;Troll 则是 build/troll。虽然这部分不是必须的,但是这样的设置可以让生成的插件以及主程序在正确的目录下,免得我们手动去复制)。DESTDIR = ../plugins,也就是相对于 build/troll 向上一级的 plugins 目录,即 build/plugins 这个目录。MOC_DIR 和 OBJECTS_DIR 指定了 moc 和 .obj 的输出目录,这里不再赘述。INCLUDEPATH 说明编译这个工程需要引入 ../GameSystem 目录下的头文件,也就是 monsterinterface.h。这么做的好处是,我们的主程序和插件共用一个接口头文件,不需要将这个头文件再复制到插件目录。最后就是插件所需要的头文件和源代码文件。
最简单的 Troll.global.h 其实是 Qt Creator 自动生成的。我们来看看里面有什么东西:
#ifndef TROLL_GLOBAL_H #define TROLL_GLOBAL_H #include <QtCore/qglobal.h> #if defined(TROLL_LIBRARY) # define TROLLSHARED_EXPORT Q_DECL_EXPORT #else # define TROLLSHARED_EXPORT Q_DECL_IMPORT #endif #endif // TROLL_GLOBAL_H
这个头文件很简单,其实是根据是否定义了TROLL_LIBRARY
宏来将TROLLSHARED_EXPORT
重新定义。TROLL_LIBRARY
这个宏就是我们在 pro 的 DEFINES 中定义的。如果TROLL_LIBRARY
已经定义,则TROLL_EXPORT
定义为Q_DECL_EXPORT
,否则的话则是Q_DECL_IMPORT
。由于我们在 Troll 插件的 pro 中定义了TROLL_LIBRARY
宏,那么TROLLSHARED_EXPORT
会被展开为Q_DECL_EXPORT
。
而 troll.h 则是这样的:
#ifndef TROLL_H #define TROLL_H #include <QObject> #include "Troll_global.h" #include "monsterinterface.h" class TROLLSHARED_EXPORT Troll : public QObject, public MonsterInterface { Q_OBJECT Q_INTERFACES(MonsterInterface) public: Troll(); QString name() const { return "Troll"; } }; #endif // TROLL_H
类 Troll 前面有TROLLSHARED_EXPORT
修饰,而前面说了这个宏将会展开为Q_DECL_EXPORT
。我们可以认为,由Q_DECL_EXPORT
修饰的类,就是被暴露(export)出的类。也就是说,现在在我们的插件中,由TROLLSHARED_EXPORT
修饰的 Troll 类已经被暴露出,可以由主程序访问到。
这个类继承了QObject
。所有的插件都必须继承自 QObject。然后,插件要声明它提供哪些服务,也就是它会实现那些接口。这里就是我们的怪物接口MonsterInterface
。下面除了Q_OBJECT
宏(这是QObject
子类所要求的),还需要使用Q_INTERFACES
告诉 Qt,这个类实现了哪些接口。MonsterInterface
接口要求有一个name()
函数,因此我们就简单的定义一个name()
。
Troll 的实现文件则更简单:
#include <QtPlugin> #include "troll.h" Troll::Troll() { } Q_EXPORT_PLUGIN2("Troll", Troll)
因为我们的接口很简单,所以 cpp 文件中基本没有什么东西。最主要的是 cpp 文件最后一行Q_EXPORT_PLUGIN2
这个宏。这个宏要求两个参数,第一个是一个字符串,代表插件的名字;第二个是插件类。
至此,我们就完成了插件 Troll。下面将其编译一下。如果没有错误,那么应该在 build 目录下有一个 plugins 目录,Troll.dll(Windows)就会出现在这个目录中。
2 评论
为什么我运行的时候总是提示我qplugin.h文件出错呢
具体是什么错误呢?