动态库是存储在磁盘上一个单独文件中的独立模块,可以被多个应用程序访问。程序通常会在连接的时候指明它们所需动态库,当该应用程序启动的时候,就会自动加载这些库。插件就是一个动态库,它为可选的额外功能提供了一个特殊的接口。使用插件来扩展Qt程序,我们通常至少需要两个类:一个是插件封装器类,它实现了插件的通用API函数,另一个是一个或多个处理器类,每个处理器类都实现了一种用于特殊类型插件的API。通过封装器类才能访问这些处理器类。
Qt插件必须放在特殊的子目录中,如果希望把Qt插件配置到不同与此的目录中,那么就需要在一开始就调用QCoreApplication::addLibraryPath()来扩展插件的搜索路径。例如样式插件必须放置在styles目录中,该目录与可执行程序处于同一位置,这是QStylePlugin的要求,否则会找不到插件。
所有的插件至少要提供一个keys()函数和一个create()函数,keys()函数会返回一个该插件可以创建的对象的列表,create()函数返回一个给定键的对象,该键必须与由keys()函数返回的列表中的一个相同。Qt中的插件类和处理器类有
插件类 | 处理器基类 |
QAccessibleBridgePlugin | QAccessibleBridge |
QAccessiblePlugin | QAccessibleInterface |
QFontEnginePlugin | QAbstractFontEngine |
QIconEnginePluginV2 | QIconEngineV2 |
QImageIOPlugin | QImagelOHandler |
QInputContextPlugin | QInputContext |
QPictureFormatPlugin | N/A |
QScriptExtensionPlugin | N/A |
QSqlDriverPlugin | QSqlDriver |
QStylePlugin | QStyle |
QTextCodecPlugin | QTextCodec |
一个应用程序插件就是实现了一个或多个接口的动态库。接口就是由专有的纯虚函数组成的类。应用程序与插件之间的通信是通过接口的虚表来完成的。接口类通常都需要声明一个虚析构函数,一个返回QStringList的虚函数和其他虚函数。
一个应用程序的插件就是QObject和它想要提供的接口的一个子类。插件的实质就是基于共享库的。
符号 - 函数、变量或类 - 包含在供客户端(例如:应用程序或其他库)使用的共享库中,必须以一种特殊的方式标记。这些符号被称为公共符号,它们被导出或公开可见。符号被设计为导出的,以便客户端可以从中导入符号。
QLibrary 用于在运行时加载共享库,一个完整的加载流程大概分为以下几步:1.构件QLibrary实例 2.setfilename()设置文件名 3.load()动态加载共享库 4.resole解析共享库中的符号 5.unload 卸载共享库 ,需将 dll 文件和可执行程序放在一起
头文件<QtPlugin>中,包含了用于插件的3个宏。Q_DECLARE_INTERFACE(ClassName,Identifier)将给定的唯一的Identifier与名为ClassName的接口类相关联。该宏通常在ClassName 的类定义之后使用,在头文件中。Q_IMPORT_PLUGIN(PluginName)该宏导入了名为PluginName的插件,参数PluginName与使用Q_PLUGIN_METADATA()的类名称相对应。Q_PLUGIN_METADATA用于声明插件的元数据,该宏需要声明接口的IID,并引用包含插件元数据的文件。