Unload Plugin in Qt 4.8
-
Hello everyone,
I'm trying to implement a plugin application that is launched from my main application by clicking on a simple button, I can't implement unloading the plugin by clicking on the close button (already in the plugin itself)
Is this possible in principle? I load the plugin using QPluginLoader and via the interface. -
The documentation says:
Once loaded, plugins remain in memory until all instances of QPluginLoader has been unloaded, or until the application terminates. You can attempt to unload a plugin using unload(), but if other instances of QPluginLoader are using the same library, the call will fail, and unloading will only happen when every instance has called unload(). Right before the unloading happens, the root component will also be deleted.
(https://doc.qt.io/qt-6/qpluginloader.html#details)
And why do you use such ancient version of Qt?
-
@Pl45m4 working on devices that not supported normal versions of qt :(, and I almost memorized the documentation about plugins, but it doesn’t really help, I’m already trying to remake my application so that the plugin sends a signal to the main application, and the main application itself unloaded this plugin, but for some reason a Segmentation fault error appears, although when checking, bool result = loader.unload)), result - true, I tried doing something else - delete loader.instance(), everything works, but if, for example, you open several plugin windows at once, for some reason only the most recently opened ones will close
-
Hi,
What do you mean by "plugin application" ?
Are you extending your application with new widgets or are you starting external applications through your plugin ? -
Do you have a stack trace of your crash ?
-
@SGaist I think it will be easier if I provide a piece of code
I have 2 app: AppPlugin and MainApp
In these two app there is a class that stores global variables:GlobalData.h
…
extern MainWindow *mainWindow;
extern QWidget *wgt;
extern QGraphicsScene *scene;
extern QGraphicsView *view;
extern QDeclarativeEngine *engine;
…
<<<<<<<<
GlobalData.cpp
…
MainWindow *mainWindow;
QWidget *wgt;
QGraphicsScene *scene;
QGraphicsView *view;
QDeclarativeEngine *engine;
…
<<<<<<<<AppPlugin:
int main(…)
{
QApplication a(argc, argv);
mainWindow = new MainWindow;
return a.exec()(
}
<<<<MainWindow.h
class MainWindow : public QObject
{
MainWindow(QObject * parent = 0);
~MainWindow();
Q_INVOKABLE unloadPlugin();
signals:
Void unloadPluginSignal();
}
<<<<
MainWindow.cpp
MainWindow::MainWindow(QObject *parent) : QObject(parent)
{
wgt = new QWidget;
…
scene = new QGraphicsScene(…);
…
view = new QGraphicsView(…);
…
engine = new QDeclarativeEngine;
//
add main.qml on scene
//
wgt->show();
}
MainWindow::~MainWindow()
{
qDebug() << “delete mainModel”;
}void MainWindow::unloadPlugin()
{
emit unloadPluginSignal();
}<<<<
PluginInterface.h
class PluginInterface : public QObject
{
Q_OBJECT
public:
virtual ~PluginInterface(){}
virtual void getEngine(QDeclarativeEngine *extEngine) =0;
Q_SIGNAL void signalFromPlugin();
};
Q_DECLARE_INTERFACE(PluginInterface, “MyTestPlugin”)<<<<<
Plugin.h
class Plugin : public PluginInterface
{
Q_OBJECT
Q_INTERFACES(PluginInterface)
public:
~Plugin();
void getEngine();
public slots:
void unloadPlugin();
}
<<<<<Plugin.cpp
Plugin::~Plugin()
{
qDebug << “delete plugin”;
}void Plugin::getEngine()
{
//
may get the engine from the main application, but in principle I don’t need it.
//
mainWindow = new MainWindow;
connect(mainWindow, SIGNAL(unloadPluginSignal()), this, SLOT(unloadPlugin()));
}
void Plugin::unloadPlugin()
{
emit signalFromPlugin();
}Q_EXPORT_PLUGIN2(PluginInterface, Plugin)
Then from main.qml I call the slot with MainWindow - unloadPlugin
main.qml
Rectangel{
…
Rectangel{
…
MouseArea{
anchors.fill: parent
onClocked: mainWindowContext.unloadPlugin()
}}
}——-/—/————————
MainApp:Int main(…)
{
QApplicatino a(argc, argv);
mainWindow = new MainWindow;
return a.exec();
}MainWindow.h
class MainWindow: public QObject
{
Q_OBJECT
public:
MainModel();Q_INVOKABLE bool loadPlugin();
public slots:
void unloadPlugin();private:
PluginInterface *plugin;
QPluginLoader *loader;
}MainWindow.cpp
MainWindow::MainWindow()
{
wgt = new QWidget;
…
scene = new QGraphicsScene(…);
…
view = new QGraphicsView(…);
…
engine = new QDeclarativeEngine;
//
add main.qml on scene
//
wgt->show();
}bool MainWindow::loadPlugin()
{
loader = new QPluginLoader(//src plugin//);
If(loader->load())
{
If( plugin = qobject_cast<PluginInterface*>(loader->instance()))
{
plugin->getEngine(engine);
connect(plugin, SIGNAL(signalFromPlugin()), this, SLOT(unloadPlugin()));
return true;
}
return false
}
}bool Plugin::unloadPlugin()
{
bool result = loader->unload();
qDebug() << result;
}after clicking on the button in ManApp and calling the loadPlugin method, it is loaded and displayed, but as soon as I click on the close button of this plugin, the unloadPlugin method is called on me and the result variable will return true, after that the application immediately crashes with segmentationFault
-
@DmitryTS said in Unload Plugin in Qt 4.8:
it is loaded and displayed, but as soon as I click on the close button of this plugin, the unloadPlugin method is called on me and the result variable will return true, after that the application immediately crashes with segmentationFault
I think because you have only one
MainWindow
pointer for the plugin and the program itself...
The "unload" clears the objects inGlobalData
and this is where you mainprogram is also stored.Othewise, as usual, debug and see where it crashes (what's the last call which causes the segfault).
-
@Pl45m4 a little bit wrong, I have this file with global variables in two programs so that the plugin has its own independent engine, at first I thought maybe this was a problem due to the same names, I’ve already renamed it - now to GlobalData in MainApp: MainWindow *appWindow
After click and call function unloadPlugin:
bool Plugin::unloadPlugin()
{
bool result = loader->unload();
qDebug() << result;
}but it crashes strangely, it outputs from the unloadPlugin method, the result variable is true and immediately segmentationFault, I tried it a little differently:
bool Plugin::unloadPlugin() { delete plugin; }
and then the program begins to have a completely different behavior, every other time it works as I need, and the frequency is incomprehensible, that is, the plugin can close normally 5 times, but break down on the 6th.I honestly still can’t fully understand, when unloading a plugin, do I need to explicitly free up memory: delete mainWindow? Or will it recursively release itself when the plugin is unloaded?
-
As already mentioned: if your app is crashing run it through debugger to see where exactly it happens and post the stack trace after the crash.