c++ - QT QLibrary "Cannot load library *.so: (*.so: undefined symbol: staticMetaObject)" -


i working on big project trying load dynamically shared library qlibrary, able reproduce run-time link error (undefined symbol: staticmetaobject) in following example:

folder structure:

root\ -- src\ ---- testlib\ ------ testlib.pro ------ derived.h ------ derived.cpp ------ testlibmodulebridge.h ------ testlibmodulebridge.cpp ---- testlibcommon\ ------ ibase.h ---- testlibmanager\ ------ testlibmanager.pro ------ main.cpp --lib\ 

testlib files:

# testlib.pro  qt       -= gui  target = testlib template = lib  qmake_cxxflags += -wall  defines += testlib_library  sources += derived.cpp \     testlibmodulebridge.cpp  headers += derived.h \     testlibmodulebridge.h  includepath += ../testlibcommon  unix {     target.path = ../../lib     installs += target } 

-

// derived.h  #ifndef derived_h #define derived_h  #include "ibase.h"  #include <iostream>  class derived : public ibase {     q_object public:     derived();     virtual ~derived();  public:     virtual void methoda();     virtual void methodb(); };  #endif // derived_h 

-

// derived.cpp  #include "derived.h"  derived::derived() {  }  derived::~derived() {  }  void derived::methoda() {     std::cout << "methoda()" << std::endl; }  void derived::methodb() {     std::cout << "methodb()" << std::endl; } 

-

// testlibmodulebridge.h  #ifndef testlibmodulebridge_h #define testlibmodulebridge_h  #include "ibase.h"  #ifdef __cplusplus extern "c" { #endif     ibase* getmoduleinterface(); #ifdef __cplusplus } #endif  #endif // testlibmodulebridge_h 

-

// testlibmodulebridge.cpp  #include "testlibmodulebridge.h" #include "derived.h"  ibase* getmoduleinterface() {     return new derived(); } 

testlibmanager files:

// testlibmanager.pro  qt       += core  qt       -= gui  target = testlibmanager config   += console config   -= app_bundle  qmake_cxxflags += -wall  template = app  sources += main.cpp  includepath += ../testlibcommon 

-

// main.cpp #include <qcoreapplication> #include <qlibrary> #include <qdebug>  #include "ibase.h"  typedef ibase* (*modulegetterfunction) (void);  int main(int argc, char *argv[]) {     qcoreapplication a(argc, argv);      qlibrary testlib("../../lib/libtestlib.so");      if (!testlib.load())     {         qdebug() << "error : " << testlib.errorstring();         exit(exit_failure);     }     else     {         modulegetterfunction getmoduleinterfacefunc = (modulegetterfunction) testlib.resolve("getmoduleinterface");          if (getmoduleinterfacefunc)         {             ibase* obj = getmoduleinterfacefunc();              obj->methoda();             obj->methodb();         }     }      return a.exec(); } 

testlibcommon files

// ibase.h  #ifndef ibase_h #define ibase_h  #include <qobject>  class ibase : public qobject {     q_object protected:     virtual ~ibase() {}  public:     virtual void methoda() = 0;     virtual void methodb() = 0; };  #endif // ibase_h 

the testlib.load() fails error : "cannot load library ../../lib/libtestlib.so: (../../lib/libtestlib.so: undefined symbol: _zn5ibase16staticmetaobjecte)"

how can fix this, removing q_object macro ibase.h fix error in production project interface contains signals , slots, , project we're not allowed change.

it looks moc has not been run before compiling testlib. moc responsible generating staticmetaobject classes contain q_object macro and listed under headers section in pro file.

adding testlibcommon\ibase.h headers in testlib.pro should fix problem. (untested).


possible improvement of solution:
instead of using qlibrary take @ qpluginloader.

qpluginloader give qobject can cast interface want using qobject_cast<t*>(pluginloader.instance())

here's example using qpluginloader: http://doc.qt.io/qt-5/qtwidgets-tools-plugandpaint-example.html


Comments