使用Qt将应用程序拆分为插件的功能

使用Qt将应用程序拆分为插件的功能

就像标题所说的那样,我想将Qt应用程序的某些部分拆分成插件,因此我可以在运行时添加新的功能.理想情况下,插件将单独编译并放入插件的专用路径中; 当应用程序启动时,安装的扩展会自动加载,或者可以随时根据用户请求重新加载.

我应该提一下,我想要插入插件的对象不是QObjects,但是如果它可以使解决方案更简单,那么它们可以继承QObject.

我怎样才能做到这一点?我想要最简单的解决方案,它是可移植的,除了Qt之外不需要任何其他东西(没有外部依赖).

1> Jarhmander..:

虽然我回答了自己的问题,但我更感兴趣的是听到别人的问题!

首先,您需要在插件之间建立一个通用接口.这是一个例子:

class MyPlugin{public: virtual ~MyPlugin() {} // Needs to be virtual. Important! // Put here your method(s) virtual void frobnicate() = 0;};

但是,不要这样命名你的界面.如果您的插件代表视频编解码器,请将其命名为”VideoCodec”.有些人喜欢在接口名称之前添加”I”(例如IVideoCodec).此外,有些人会告诉你有公共方法调用受保护的虚拟机,但那里并不是绝对必要的.

为何选择界面?这是因为它是应用程序在不事先知道类本身的情况下使用插件的唯一方法.这意味着因为应用程序不知道类,所以插件必须允许通过工厂创建插件组件.实际上,声明的唯一必需函数是一个工厂函数,它创建一个”插件”的新实例.此工厂函数可以声明为:

extern “C” std::unique_ptr MyPlugin_new();

(你需要extern “C”,否则你会QLibrary因为C++名称错误而遇到麻烦- 见下文)

工厂功能不必没有参数,但参数必须适用于所有类型的插件.例如,这可以是散列表或包含一般配置信息的文件,或甚至更好的是用于配置对象的接口.

现在装载部分.最简单的方法是使用QDirIterator初始化到插件目录,遍历所有文件并尝试加载它们.有点……

void load_plugins_from_path(const QString &plugin_dir){ QDirIterator it(plugin_dir, QDir::Files, QDir::Readable); while (it.hasNext()) { try_load_plugin(it.next()); }}

(它写得像是一个函数,但应该是一个方法)

不要以任何方式尝试通过扩展或使用QDir::Executable标志来过滤文件:这将不必要地降低程序的可移植性 – 每个操作系统都有自己的文件扩展名,并且QDir::Executable只能在unices上工作(可能因为Windows上没有exec位) ).这里,该方法load_plugins_from_path只是从一个给定的路径加载插件; 例如,调用者可以在列表的元素上调用该方法,该列表包含搜索插件的所有路径.try_load_plugin可以像这样定义:

void try_load_plugin(const QString &filename){ QLibrary lib(filename); auto factory = reinterpret_cast(lib.resolve(“MyPlugin_new”)); if (factory) { std::unique_ptr plugin(factory()); // Do something with “plugin”, e.g. store in a std::vector }}

decltype上使用MyPlugin_new,所以我们不必指定其类型(std::unique_ptr (*)()),并使用它auto会为你节省更多的变化比它需要的是代码的麻烦,你应该改变的签名MyPlugin_new.

此方法只是尝试将文件作为库加载(无论它是否是有效的库文件!)并尝试解析所需的函数,nullptr如果我们没有处理有效的库文件或请求的符号(我们的函数),则返回)不存在.请注意,因为我们直接在动态库中进行搜索,所以我们必须知道该库中实体的确切名称.因为C++破坏了名称,并且修改依赖于实现,所以唯一明智的做法是使用extern “C”函数.不过不用担心:extern “C”只会阻止该函数的重载,否则所有C++都可以在该函数内部使用.此外,即使工厂函数不在任何命名空间内,它也不会与其他库中的其他工厂函数冲突,因为我们使用显式链接 ; 这样,我们可以 MyPlugin_new从插件A和MyPlugin_new插件B中获得它们,它们将位于不同的地址.

最后,如果你的插件集太多而不能用一个接口表示,那么一个解决方案就是简单地定义(可能)插件内部的多个工厂,每个工厂都返回一个指向不同类型接口的指针.

这是实现您所要求的最佳方式.在设置赏金后,我没有看到回答你自己的问题的观点….


比丘资源网 » 使用Qt将应用程序拆分为插件的功能

发表回复

提供最优质的资源集合

立即查看 了解详情