Search code examples
c++qtcmakelinkerdllexport

Qt object's staticMetaObject address different in executable than linked dll


I'm having an issue with the address of a QObject's staticMetaObject being different when read from my main executable's code vs. from a dll loaded using a QPluginLoader. The class in question belongs to the loaded DLL. The DLL is also linked at build time for different reasons. This issue is causing a qobject_cast to fail, because the template argument I give has a different staticMetaObject than what the metaObject() method returns, and the meta object system compares addresses of meta objects to check inheritance.

What makes it confusing is that this only seems to happen on Windows, and further still it only happens if I use CMake instead of QMake.

It must be my build instructions, but I don't know enough about library linkage to know. I would have chalked this up to it being the fact that a static variable inside a DLL loaded at runtime will of course have a different address, but I don't understand why this doesn't happen with the QMake version of my project.

It feels like a symbol visibility/export issue.

I have tried setting WINDOWS_EXPORT_ALL_SYMBOLS or just adding -Wl,--export-all-symbols to all targets, but nothing changed. The library is linked using target_link_libraries(exe PRIVATE dll), where dll is the library in question.


Solution

  • Seems it was user error. In order to run straight from the build directory, Qt Creator offers to add build library paths to your run environment, but for CMake that doesn't work well, so I had to add CMake instructions to copy the DLL to the executable's folder. The plugin loader was referencing the DLL inside a lib subfolder in the build directory, but the DLL opened as part of the executable starting was the one in the same directory.

    Two identical DLLs, but different locations. My guess is since the one in the executable directory is already open by the executable, opening it again with the plugin loader reuses the addresses of things, but if opened with a different path, it's different address space.

    I didn't see our plugin loader searching outside the executable directory, so I fixed that and it works now.