Inheritance of plugins with QPluginLoader not working?
-
Hello everybody,
I am having some major issues with inheritance in between plugins and the ability
to load/cast them properly at runtime. Let me describe the problem. I will also provide
the whole project tree so you can try it out yourself.I have two interfaces: Parent/ChildInterface, linked by a natural inheritance relation:
@
class ParentInterface{};
Q_DECLARE_INTERFACE(ParentInterface, "ParentInterface/1.0")
class ChildInterface : public ParentInterface{};
Q_DECLARE_INTERFACE(ChildInterface, "ChildInterface/1.0")
@Then I have two plugins (PluginChild/Parent), each respectively implementing the
corresponding interface:
@
class PluginChild : public QObject, public ChildInterface{ //...
class PluginParent : public QObject, public ParentInterface{ //...
@Now I load the plugins at runtime using what follows:
@
QObject *plugin = loader.instance();
if( plugin ){
qDebug() << "==> Loaded correct QPlugin";ChildInterface* iC = qobject_cast<ChildInterface*>(plugin); if(iC) qDebug() << "==> ChildInterface CASTED"; else qDebug() << "==> ChildInterface FAILED"; ParentInterface* iP = qobject_cast<ParentInterface*>(plugin); if(iP) qDebug() << "==> ParentInterface CASTED"; else qDebug() << "==> ParentInterface FAILED"; } else qDebug() << "==> Load incorrect QPlugin";
@
And this is the output I get:
@
Loading: "/Users/ata2/workspace/starlab/tester/plugins/libplugin_child.dylib"
==> Loaded correct QPlugin
==> ChildInterface CASTED
==> ParentInterface FAILED
Loading: "/Users/ata2/workspace/starlab/tester/plugins/libplugin_parent.dylib"
==> Loaded correct QPlugin
==> ChildInterface FAILED
==> ParentInterface CASTED
@The question is simple: why libplugin_child fails during casting ParentInterface?
The full source tree is available in a compressed zip "HERE":http://www.sfu.ca/~ata2/tester.zipThank you so much for your input
Andrea Tagliasacchi
-
You are most probably missing a Q_INTERFACES(ParentInterface) in your PluginChild.
qobject_cast() relies on the information provided by the meta object system, which requires you to specify any implemented interfaces using Q_INTERFACES() (and all QObject classes to specify Q_OBJECT). ParentInterface and ChildInterface are not QObjects and so there is no meta object information (and thus qobject_cast() cannot work).
However, ParentInterface is still a parent class of ChildInterface (in terms of C++ inheritance). So once you have cast a plugin to ChildInterface using qobject_cast(), you can cast it to ParentInterface implicitly or explicitly using static_cast().
@
ChildInterface* iC = qobject_cast<ChildInterface*>(plugin);
ParentInterface* iP = static_cast<ParentInterface*>(iC);
@ -
Thanks Lukas, I understand the problem. The source of it was in the full project.
In there I had the following@
class SurfaceMeshIO : public ModelIO{
Q_INTERFACES(ModelIO)
...
@@ // Source of error
class io_surfacemesh_off : public QObject, public SurfaceMeshIO{
Q_OBJECT
Q_INTERFACES(SurfaceMeshIO)
....
@I was assuming that since "io_surfacemesh_off" inherited from SurfaceMeshIO, the Q_INTERFACE(ModelIO) was already taken care of from its superclass. I have to admit, it's kind of weird that I have to do what follows:
@ // Correction
class io_surfacemesh_off : public QObject, public SurfaceMeshIO{
Q_OBJECT
Q_INTERFACES(SurfaceMeshIO)
Q_INTERFACES(ModelIO)
....
@