Relocation against undefined hidden symbol
-
Hi,
I have 2 (dynamic) libraries. The first one defines a base class like this:#define Q_MPI_MESSAGE \ Q_GADGET \ public: \ virtual const QMetaObject * metaObject() const { return &staticMetaObject; } class Q_DECL_EXPORT QMpiMessage { Q_MPI_MESSAGE public: QMpiMessage(); virtual ~QMpiMessage(); };
While the latter library defines concrete implementation(s). E.g:
class Q_DECL_HIDDEN AedMpiUpdateNucleus : public QMpiMessage { Q_MPI_MESSAGE public: explicit AedMpiUpdateNucleus(AedNucleus * = nullptr); };
The
AedMpiUpdateNucleus
class is needed and used only inside the library and should not be part of the public binary interface, so it is not exported. Whenever I built the above, however, I get the following error:../bin/debug/obj/aedmpimessages.o: In function `AedMpiUpdateNucleus::metaObject() const': /home/nye/Programming/C++/aed/aed-core/aedmpimessages.h:13: undefined reference to `AedMpiUpdateNucleus::staticMetaObject' /usr/bin/ld: ../bin/debug/obj/aedmpimessages.o: relocation R_X86_64_PC32 against undefined hidden symbol `_ZN19AedMpiUpdateNucleus16staticMetaObjectE' can not be used when making a shared object
Here's what I've come up with in my investigations:
- If I export the
AedMpiUpdateNucleus
class the problem disappears, I don't want to do that though. - Replacing my own macro with its contents also solves the issue and this looks like a subtle
moc
limitation I've hit. Ideally, I'd like to keep everything in my macro as such.
My suspicion is that the linker gets confused about having a static member (namely
staticMetaObject
) in two classes one of which is hidden, so it couldn't create the relocation rules correctly - case 1).
As for case 2), if I recall correctlymoc
should be fine expanding macros, and unlessQ_GADGET
has some special meaning I see no reason why 2) really works.Any suggestions and/or detailed explanations for why this happens are very welcome.
Thanks in advance! - If I export the
-
I have found the proper solution to this problem. It's not the
moc
per se, it's how the generatedcpp
file is linked in the binary.
Anyway, without going into the ugly details, to solve this, one must simply include the generatedmoc_xxx.cpp
file into the regular class's implementation.cpp
file.
In my case I had to includemoc_aedmpimessages.cpp
inaedmpimessages.cpp
to make it work correctly.