我遇到的问题是,从主可执行文件的代码读取的 QObject
staticMetaObject
的地址与从使用 QPluginLoader
加载的 dll 读取时的地址不同。有问题的类属于加载的 DLL。由于不同的原因,DLL 也在构建时被链接。此问题导致 qobject_cast
失败,因为我给出的模板参数的 staticMetaObject
与 metaObject()
方法返回的不同,并且元对象系统会比较元对象的地址以检查继承。
令人困惑的是,这似乎只发生在 Windows 上,而且只有当我使用 CMake 而不是 QMake 时才会发生。
这一定是我的构建指令,但我对库链接了解不够。我认为这是因为运行时加载的 DLL 内的静态变量当然会有不同的地址,但我不明白为什么我的项目的 QMake 版本不会发生这种情况。
感觉像是符号可见性/导出问题。
我尝试设置
WINDOWS_EXPORT_ALL_SYMBOLS
或仅将 -Wl,--export-all-symbols
添加到所有目标,但没有任何改变。该库使用 target_link_libraries(exe PRIVATE dll)
进行链接,其中 dll
是相关库。
似乎是用户错误。为了直接从构建目录运行,Qt Creator 提供了将构建库路径添加到运行环境的功能,但对于 CMake 来说效果不佳,因此我必须添加 CMake 指令以将 DLL 复制到可执行文件的文件夹中。插件加载程序引用构建目录中
lib
子文件夹内的 DLL,但作为可执行文件启动的一部分打开的 DLL 是同一目录中的 DLL。
两个相同的 DLL,但位置不同。我的猜测是,由于可执行目录中的目录已经被可执行文件打开,因此使用插件加载器再次打开它会重用事物的地址,但如果使用不同的路径打开,则它是不同的地址空间。
我没有看到我们的插件加载器在可执行目录之外搜索,所以我修复了这个问题,现在它可以工作了。