Relocation against undefined hidden symbol

  • Qt Champions 2016

    Re: Meta-type id of an object

    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
        virtual ~QMpiMessage();

    While the latter library defines concrete implementation(s). E.g:

    class Q_DECL_HIDDEN AedMpiUpdateNucleus : public QMpiMessage
        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:

    1. If I export the AedMpiUpdateNucleus class the problem disappears, I don't want to do that though.
    2. 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 correctly moc should be fine expanding macros, and unless Q_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!

  • Qt Champions 2016

    I have found the proper solution to this problem. It's not the moc per se, it's how the generated cpp file is linked in the binary.
    Anyway, without going into the ugly details, to solve this, one must simply include the generated moc_xxx.cpp file into the regular class's implementation .cpp file.
    In my case I had to include moc_aedmpimessages.cpp in aedmpimessages.cpp to make it work correctly.

Log in to reply

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.