如何创建Qt Plugins (插件)之 使用低级api

使用低级的api:扩展Qt的应用程序

不仅仅是Qt 本身,Qt的应用程序也可以通过plugins来扩展。这个就要求应用程序来探测和加载插件通过QPluginLoader.在这个前提下, 插件可以提供任意的函数,就不会局限于database drivers, image formats, text codecs, styles, 和一些其他可以扩展Qt功能类型的插件。


制作应用程序插件的扩展可以通过如下的步骤:

  1. 定义接口的集合(类的纯虚函数)跟随这个插件plugins.
  2.  使用这个Q_DECLARE_INTERFACE()宏来告诉Qt的元对象系统关于这个接口。
  3. 使用QPluginLoader在应用程序中来加载这些插件.
  4. 使用qobject_cast()来告诉插件实现给定的接口。
写一个插件包括下面的步骤:
  1. 声明一个插件类继承自QObject,或者从这个插件想提供的接口;
  2. 使用Q_INTERFACE()宏来告诉Qt的元对象系统关于这个这个插件;
  3. 导出这个插件通过使用Q_PLUGIN_METADATA()宏;
  4. 编译插件通过使用合适的.pro  文件。
例如,这有一个定义的接口类:
class FilterInterface
{
public:
    virtual ~FilterInterface() {}

    virtual QStringList filters() const = 0;
    virtual QImage filterImage(const QString &filter, const QImage &image,
                               QWidget *parent) = 0;
};


这定义的插件类的实现接口:
#include <QObject>
#include <QtPlugin>
#include <QStringList>
#include <QImage>

#include <plugandpaint/interfaces.h>

class ExtraFiltersPlugin : public QObject, public FilterInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface" FILE "extrafilters.json")
    Q_INTERFACES(FilterInterface)

public:
    QStringList filters() const;
    QImage filterImage(const QString &filter, const QImage &image,
                       QWidget *parent);
};


Plug&Paint的例子文档解释了这个过程的细节。查看Creating Custom Widgets for Qt Designer 获取一些关于Qt Designer的特定的问题的细节。你也可以看下Echo Plugin Example查看如何实现扩展一个Qt application的插件的实现的更详细过程。注意QCoreApplication必须在插件加载之前就已经初始化过了。


 定位插件

Qt application将会自动感知可获取的插件,因为插件都被存储在标准的子目录当中。因此引用程序不需要任何查找或者加载插件的代码。


在开发过程中, 插件的目录是 QTDIR/plugins(而QTDIR就是Qt所在的安装目录),每个类型的插件放在这个类型的子目录下面。例如,styles. 如果你想要你的应用程序使用插件,而你不想用标准的插件存放路径,那你的安装过程就决定了你想要使用插件的路径,例如,使用QSettings, 应用程序就需要在运行时读取设置文件。application可以通过QCoreApplication::addLibraryPath()来获取你所定义的应用程序要用到的插件。

注意:最后部分的路径(例如,styles)是不会改变的。


如果你想这个插件是可以被加载的,其中一个方式就是在这个应用程序下面创建子目录,并将插件放在这个目录中。如果你想用Qt分布任意的插件(就是可以将插件存储在本地目录),你必须拷贝这个插件下的子目录,当这个插件位于应用程序的根目录下(也就是说,不包括plugins的目录)。


查看更多的开发的信息,查看Deploying Qt Applications 和Deploying Plugins的文档。


静态插件

应用程序使用插件的最灵活和普遍的方式就是通过动态库,单独使用,独立的查找和实时加载。


Plugins也可以静态链接到你的程序中,如果你编译Qt的静态版本,这是包含Qt的预定义的插件的唯一选择。使用静态插件使用开发可以插件部署更少的出错,但是这种方式同样有缺点,就是没有办法加载功能插件,包括不能完整的重编译和重新部署的应用程序。


为了静态连接插件,你可以通过使用QTPLUGIN加载需要的plugins到你的编译中。

在.pro文件中,你需要如下的条目:

QTPLUGIN     += qjpeg \
                qgif \
                qkrcodecs

qmake将会自动加载这些插件到QTPLUGIN,他们通常将被Qt modules使用(see QT), 同时,更多特定的插件将被手动添加。这个默认被自动添加的插件将被每个类型自动重载。例如,连接最小的插件而不是默认Qt平台移植的插件,通过:

QTPLUGIN.platforms = qminimal

如果你既不想使用默认插件,也不想使用最小的QPA plugin被自动连接,使用:

QTPLUGIN.platforms = -
默认值被调到一个开箱即用的最佳情况,但是可能使程序变臃肿。推荐使用命令行检查,用qmale编译,消除一些不必要的插件。

链接静态插件的细节

为了静态插件被真实的链接和实例化,Q_IMPORT_PLUGIN() 宏需要在application的代码中使用,但是他们也是通过qmake自动编译产生并添加到你的程序中的。

如果你不想所有的插件被添加到QTPLUGIN中,被自动连接,移除 import_plugins  从这个 CONFIG中:

CONFIG -= import_plugins
创建静态插件

这个是可能的创建自己的静态插件,通过下面的几个步骤:

  1. 添加 CONFIG += static 在插件的.pro文件中。
  2. 使用Q_IMPORT_PLUGIN()宏在你的application中。
  3. 使用Q_INIT_RESOURCE()宏在你的应用程序的插件qrc文件中。
  4. 链接你的插件在程序中,通过在.pro文件中使用LIBS.
查看Plug&Paint的例子来关联Basic Tools插件获取实现的细节。
注意:如果你不使用qmake来编译你的插件你需要保证QT_STATICPLUGIN通过定义预处理的宏。

部署和调试插件

这个Deploying Plugins的文档覆盖了处理部署应用程序的插件。
也可以查看QPluginLoader, QLibrary,和Plug&Paint Example.



阅读更多
个人分类: qt
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭