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
Post a Comment