Reputation: 4821
I am in the process of building a Qt application. While I have programmed lots of GUI things before and the framework itself isn't presenting a problem, I have not ever programmed anything (outside of C# .NET applications) that has the capability to load plugins. The project I am trying to build has plugins as an integral part of it and I thought the Qt framework looked nice for this because it was almost universally cross-platform and seems to have a very nice system for plugins.
My problem is this: I can't seem to get the QPluginLoader.instance() method to return anything but a null value.
From my readings, this is because it finds no plugin. I think I am probably forgetting to do something, but I can find very little documentation on actually writing plugins (there are examples, but they aren't incredibly detailed). There are plenty of examples of loading plugins and I think I am doing that right, but I haven't really found an example of actually making a plugin.
This is what I have done:
Using Qt-Creator I have created two projects: A windowed application to pretend that it is my plugin receiving application and a Shared Library project to pretend to be the plugin
In my windowed application I have a header file as follows:
#ifndef PLUGININTERFACE_H
#define PLUGININTERFACE_H
#include <QtPlugin>
class QStringList;
class PluginInterface
{
public:
virtual ~PluginInterface() {};
virtual QStringList messages() const = 0;
};
Q_DECLARE_INTERFACE(PluginInterface,
"com.kevincuzner.LearningPlugins.PluginInterface/1.0")
#endif // PLUGININTERFACE_H
In my shared library application I created a class called ATestPlugin (and this is also the TARGET value of the project):
#ifndef ATESTPLUGIN_H
#define ATESTPLUGIN_H
#include "ATestPlugin_global.h"
#include "../LearningPlugins/PluginInterface.h"
#include <QStringList>
class ATESTPLUGINSHARED_EXPORT ATestPlugin : public PluginInterface, public QObject
{
Q_OBJECT
Q_INTERFACES(PluginInterface)
public:
ATestPlugin();
virtual QStringList messages() const
{
//this part is actually defined in the .cpp file, but I don't feel like pasting that here
QStringList ret;
ret << "foo" << "bar" << "noms" << "Hello";
return ret;
}
};
#endif // ATESTPLUGIN_H
At the end of the ATestPlugin.cpp file I have placed Q_EXPORT_PLUGIN2(ATestPlugin, ATestPlugin)
Then in my main.cpp file in the main method I do the following (&w points to the main window):
QString text = QFileDialog::getOpenFileName(&w, "Get a file");
QPluginLoader loader(text);
QObject* plugin = loader.instance();
if (plugin)
{
QMessageBox msgBox;
msgBox.setText(text);
msgBox.exec();
}
When I run the program and select libATestPlugin.so from the build directory of my library project in the file dialog that pops up, I see no message box which means *plugin is null. Previously I had the messagebox always pop up and show the selected file name, so I know that part is working.
Does anyone have any ideas as to what I need to do to make my plugin visible to QPluginLoader?
Upvotes: 0
Views: 4474
Reputation: 41
It didn't work for me. Change of your previous TARGET to $$qtLibraryTarget(...) ensures right extensions during build on different platforms.
I had the same problem with QPluginLoader. In few words how I solved it: I create plugin library, let's say lib1.dll which use some stuff from lib2.dll. In my application I try to load lib1 via QPluginLoader.
QPluginLoader loader( adaptersDir.absoluteFilePath(fileName) );
AdapterInterface* adapterIface = qobject_cast<AdapterInterface*>(loader.instance());
In this case loader.instance() returns 0. Solution was to copy lib2.dll into application folder because an application use it for proper load plugin lib1.
Upvotes: 1
Reputation: 4821
After further experimentation I managed to get the plugin to load. I feel sheepish saying this, but it was a classic case of RTFM.
The echo plugin tutorial (which I hadn't found until after I posted the question) had some modifications that had to be made to the .pro file in the library to make it declare the plugin correctly:
The line TARGET = ATestPlugin
had to be changed to TARGET = $$qtLibraryTarget(ATestPlugin)
. After making this change, my messagebox in the above program popped up and later when I ran qobject_cast< PluginInterface* >(plugin)
and then asked ran PluginInterface->messages()
I got the list which was implemented in the separate class.
Also, I did change the inheritance order to put QObject first and since it works that way I will probably keep it so (although, I don't know if it made a difference).
Upvotes: 0