【问题标题】:Qt: How to manage QObject classes across dll and executable?Qt:如何跨 dll 和可执行文件管理 QObject 类?
【发布时间】:2021-11-10 23:10:10
【问题描述】:

我在 Win10 中有一个 Qt+cmake 项目。 项目结构是

  • 主要
    • 主窗口
  • DLL1
    • 1 类
  • DLL2
    • 2 类

Class1 和 Class2 都是 QObject 的子类。 MainWindow 作为一个可执行文件,包括 Class1 和 Class2。 Class2 包括 Class1。但是,编译器警告:

mocs_compilation.cpp.obj:-1: error: LNK2019: unresolved external symbol "public: static struct QMetaObject const Class1::staticMetaObject" ...
Class2.cpp.obj:-1: error: LNK2001: unresolved external symbol "public: static struct QMetaObject const Class1::staticMetaObject" ...

我已经完成了:

  1. 定义用于从 dll 导出类的宏。
#if defined(DLL_DECL)
#define DLL_DECL_SPEC Q_DECL_EXPORT
#else
# define DLL_DECL_SPEC Q_DECL_IMPORT
#endif
  1. Class1 就是这样定义的。
class DLL_DECL_SPEC Class1: public QObject
{
    Q_OBJECT
    ...
}
  1. Class1 可以在 MainWindow 中成功实例化。
  2. 当 Class2 包含 Class1 时,编译总是失败并出现上述错误。

我试过了:

  1. 其他非 QObject 类可以在 MainWindow 和 Class2 中成功实例化。
  2. 我已经检查了 target_link_libraries。主要链接 DLL1 和 DLL2。 DLL2 链接 DLL1。
  3. 我尝试在 Class2 的标头中仅通过其名称声明 Class1,在 Class2 的 cpp 中声明 #include "Class1.h"。错误仍然存​​在...

您对这些错误有任何想法吗?在 Qt 中,一个 QObject 类是否只允许使用一次?有什么办法可以解决吗?

感谢您的任何建议!

【问题讨论】:

  • 我没有做任何特别的事情(在 dll 中正常导出符号)来完成这项工作。是的,我正在使用 Qt + CMake + dlls + Visual Studio,
  • 您必须为每个 .dll 设置单独的 DLL_DECL_SPEC(每个都只在其自己的 .dll 中定义)。 dll),所以你需要#if defined(DLL_DECL1) #define DLL_DECL_SPEC1 ...#if defined(DLL_DECL2) #define DLL_DECL_SPEC2 ...P.S.:这与 Qt 无关。 :)
  • 谢谢克里斯蒂法蒂!和你说的完全一样。我重命名了宏并解决了。 :)

标签: c++ windows qt dll qobject


【解决方案1】:

正如 CristiFati 提到的,我为每个动态库创建了一个 ModuleXX.h。

#if defined(DLL_DECLXX)
#define DLLXX_DECL_SPEC Q_DECL_EXPORT
#else
# define DLLXX_DECL_SPEC Q_DECL_IMPORT
#endif

在 CMakeLists.txt 中,我将定义重命名为 add_definitions(-DDLL_DECLXX)。现在包含问题已经解决了。

【讨论】:

  • 这会使链接器静音,但不能解决您的实际问题。见Potential Errors Passing CRT Objects Across DLL Boundaries
  • @IInspectable:为什么您认为真正的问题仍未解决?这是一个经典的__declspec(dllexport)__declspec(dllimport) 不匹配示例。 .dll 边界交叉 + 静态 UCRTs 是另一个通用问题,但我没有看到问题中提到后者。
  • @cri 您没有看到提到的后一个问题,因为它是一个很难调试并归因于任何根本原因的问题,大多数人只会继续前进并将其订阅到时髦的操作系统。
  • 没错,是Undefined Behavior,但在IDE中,默认选择/MD(d)(我想在命令行上是一样的,但我现在不在 Win 上确认/确认)。因此,除非没有明确改变这一点,否则不会遇到问题。我假设 OP 如果他们这样做了会提到这个事实,(这就是为什么我说我在问题中没有看到它)。
  • @cri /MD[d] 命令行选项不足以防止潜在问题。
猜你喜欢
  • 1970-01-01
  • 2015-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-17
  • 1970-01-01
相关资源
最近更新 更多