我的问题是在使用Qt插件时如何进行正确的对象/资源管理。默认的RAII似乎与Qt不兼容。
在我们的应用程序中,我们使用模块(Qt插件),它们在运行时动态加载。当加载插件时,插件可以初始化自己,并作为初始化阶段的一部分将自己的小部件添加到应用程序中。 - 到工具栏 - 到侧面板 - 等等。 添加到主窗口的小部件也会转移它们的所有权。
这一切都很好,但现在我们的应用程序变得更加复杂,我们还需要注意关闭阶段。简单地卸载模块会让我们陷入各种麻烦。不存在的对象或仍然存活的对象类型已被卸载。
为了实现可靠的关闭,似乎唯一正确的方法是进行反向初始化。这也意味着每个将小部件添加到主窗口的模块也必须将它们删除。尝试使用第一个小部件就已经让我陷入了麻烦。
模块A向MainWindow注册小部件W。最好我想返回一个作用域对象,在作用域结束时删除和释放小部件。然而,已经看出来,给定小部件W,你不能简单地从工具栏中删除它,因为它使用操作(删除操作不会删除小部件!请参见下面的示例)。
总之,我认为Qt是以这样一种方式制作的,它获得了所有权,你必须依靠Qt来删除它。这在模块中效果不佳。我在寻找一个解决方案/最佳实践。
编辑:
我添加了一个示例,其中一个模块将自定义小部件添加到MainWindow的工具栏中。出于上述原因,我的目标是使该模块负责删除小部件。该示例旨在使问题更加具体化。它代表了使用此模式与插件相结合的通用问题-qt对象的所有权。
示例:
executable.cpp
在我们的应用程序中,我们使用模块(Qt插件),它们在运行时动态加载。当加载插件时,插件可以初始化自己,并作为初始化阶段的一部分将自己的小部件添加到应用程序中。 - 到工具栏 - 到侧面板 - 等等。 添加到主窗口的小部件也会转移它们的所有权。
这一切都很好,但现在我们的应用程序变得更加复杂,我们还需要注意关闭阶段。简单地卸载模块会让我们陷入各种麻烦。不存在的对象或仍然存活的对象类型已被卸载。
为了实现可靠的关闭,似乎唯一正确的方法是进行反向初始化。这也意味着每个将小部件添加到主窗口的模块也必须将它们删除。尝试使用第一个小部件就已经让我陷入了麻烦。
模块A向MainWindow注册小部件W。最好我想返回一个作用域对象,在作用域结束时删除和释放小部件。然而,已经看出来,给定小部件W,你不能简单地从工具栏中删除它,因为它使用操作(删除操作不会删除小部件!请参见下面的示例)。
总之,我认为Qt是以这样一种方式制作的,它获得了所有权,你必须依靠Qt来删除它。这在模块中效果不佳。我在寻找一个解决方案/最佳实践。
编辑:
我添加了一个示例,其中一个模块将自定义小部件添加到MainWindow的工具栏中。出于上述原因,我的目标是使该模块负责删除小部件。该示例旨在使问题更加具体化。它代表了使用此模式与插件相结合的通用问题-qt对象的所有权。
示例:
executable.cpp
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0) {
ui->setupUi(this);
LoadPlugin();
}
void LoadPlugin() {
m_plugin = new QPluginLoader("module.dll");
m_plugin->load();
IModule* moduleInstance = qobject_cast<IModule*>(m_plugin->instance());
moduleInstance->Initialize(this);
}
void AddToolbarSection(QWidget* widget) {
/** ownership is transferred here to Qt */
mainToolBar->insertWidget(pWidget);
}
void RemoveToolbarSection(){
/** How to get the widget deleted? */
}
/** this is called before the destructor */
void UnloadPlugin() {
moduleInstance->Shutdown();
m_plugin->unload();
}
~MainWindow() {
/** deletion of toolbar sections must already been done here
as the modules are already unloaded. Otherwise access violations occur
because specific type information is not accessible anymore.
*/
}
private:
Ui::MainWindow *ui;
QPluginLoader* m_plugin;
IModule* m_moduleInstance;
};
module.cpp
class EXPORT_MODULE IModule : public QObject
{
Q_OBJECT
Q_PLUGIN_METADATA(IID IModuleIID)
Q_INTERFACES(IModule)
public:
IModule() {
}
void Initialize(QMainWindow* window) {
/** QMyToolbarSectionWidget is a custom widget defined in this module (module.dll)
it has a specific destructor and triggers all kinds application
specific cleanup */
m_toolbarSection = new QMyToolbarSectionWidget();
window->AddToolbarSection(m_toolbarSection);
}
void Shutdown() {
window->RemoveToolbarSection(m_toolbarSection);
}
private:
QWidget* m_toolbarSection;
};