QT MetaObject从单独的动态库进行检查

Qt MetaObject inheritance checking from separate dynamic libraries

本文关键字:动态 进行检查 单独 MetaObject QT      更新时间:2023-10-16

我正在创建一组具有常见基本类型的QT插件。该应用程序加载一个插件并根据其是哪个基本类型的孩子进行分类。

基本类型包含在静态库中,派生类型内置在插件中,包括静态库,并且该应用程序还链接到静态库。

简化,这看起来像:

静态库(common)

class Base1 : public QObject {
    Q_OBJECT
};
// Qt moc code generation:
//    const QMetaObject Base1::staticMetaObject = {&QObject::staticMetaObject, /*etc*/};
class BasePlugin {
    public:
        virtual QObject* getObject()=0;
};

共享库(插件)

class Derived1 : public Base1 {
    Q_OBJECT
};
// Qt moc code generation:
//     const QMetaObject Derived1::staticMetaObject = {&Base1::staticMetaObject, /*etc*/};
class Derived1Plugin: public QObject, public BasePlugin {
    Q_OBJECT
    public:
        QObject* getObject() { return new Derived1; }
};

应用程序

// setup plugin loader, load plugin
QObject* pluginObj = plugin.instance();
qDebug() << qobject_cast<Base1*>(pluginObj);    // Displays 0x0
qDebug()
      << pluginObj->metaObject()->superClass()  // Displays two different 
      << &Base1::staticMetaObject;              // pointer addresses

经过一番挖掘,本质上发生的事情是Base1的元主体是Base1的静态数据成员,并且两次初始化:一次在共享库中,一次在应用程序中。MetaObject Derived1::staticMetaObject在插件中初始化了,并指向插件中初始化的Base1::staticMetaObject,并且在应用程序中,App中的名称Base1::staticMetaObject指向APP中初始化的MetaObject。MSVC和GCC都是如此。因此,QT确定插件的派生类与应用程序的基类不兼容。

我的问题是:

  • 如何在多个可执行文件中包含静态成员?
  • 有更好的方法可以做我试图做的事情吗?
  • 如何让我的应用识别Derived1继承Base1

我通过使用q_declare_interface和q_interfaces宏。

扩展QT应用程序的文档说明了这些宏的使用,但并非所有插件机械对于动态铸件都必须使用。

class BaseInterface
{
public:
  virtual ~BaseInterface() {}
  virtual void foo() = 0;
};
Q_DECLARE_INTERFACE( BaseInterface, "org.example.BaseInterface" )
class Base1 : public QObject, public BaseInterface
{
   Q_OBJECT
   Q_INTERFACES( BaseInterface )
public:
   virtual void foo() override {}
};

您现在应该能够使用qobject_cast< BaseInterface* >(pluginObj)

理论上,您还可以将Base1本身定义为接口,并将Q_INTERFACES( Base1 )添加到Derived1的声明中,但是在尝试执行此操作时,我遇到了qtbug-59460,此外,这意味着每个类别继承Base1都必须记住要记住添加该宏。