如何在macOS共享库中停止重复的QMetaObject定义

How can I stop duplicate QMetaObject definitions across macOS shared libraries?

本文关键字:定义 QMetaObject macOS 共享      更新时间:2023-10-16

以下qobject_cast()在macOS 10.12.2/clang上失败(在RHEL6/gcc上工作),因为我们的Handler类有重复的QMetaObject定义:

void AbstractDataView::getSelected()
{
qDebug() << Q_FUNC_INFO << QObject::sender()
<< QObject::sender()->metaObject()
<< &Handler::staticMetaObject;
Handler *h = qobject_cast<Handler*>(QObject::sender());
if(h)
this->getSelected(h);
else
qDebug() << "could not find handler to get selected data points"
<< h;
}

以上打印:

DEBUG: void AbstractDataView::getSelected() Handler(0x7f9674011780, name = "Export Metadata-7f9674011780") 0x1009d4930 0x1113a1310 
DEBUG: could not find handler to get selected data points QObject(0x0)

上述代码位于我们的应用程序加载的共享库插件中(通过Qt插件宏Q_DECLARE_INTERFACE等实现);CCD_ 5类(源自QAction)实例由可执行文件构造并传递给共享库插件构造函数。Handler是在一个静态库中定义的,该静态库内置于应用程序和共享库插件中。

这似乎描述了我的问题,并表明我需要将Handler定义编译到它自己的动态库(而不是静态库)中。因为这会引起很多头痛:

  • 这真的是我的问题吗:将Handler移动到共享库并在应用程序和现有插件中动态加载它真的能解决这个问题吗
  • 真的没有更简单的方法来解决这个问题吗,特别是因为它在linux(RHEL6)上运行良好

如果有帮助的话,我可以提供CMakeList片段,但我认为这已经足够长了。

我自己可以提供一个勉强令人满意的答案,但我希望有人能提供更好的答案。简而言之:

  • Handler移动到共享库确实有效。。。有点
  • 我发现唯一"更简单"的解决方法是使用reinterpret_cast<Handler*>。从某种意义上说,这"有效",我没有发现直接的问题,但我肯定不相信它,而且事实证明,共享库解决方案只涉及很少(我考虑使用动态加载而不仅仅是链接)

这样做之后,我确实得到了一个QMetaObject:

DEBUG: void AbstractDataView::getSelected() Handler(0x7fa9eae0b9e0, name = "Export Metadata-7fa9eae0b9e0") 0x10e840350 0x10e840350

但是qobject_cast仍然失败!幸运的是,dynamic_cast<>确实有效(所以我有比reinterpret_cast<>更安全的东西),但我不能说我完全理解发生了什么。