2015-07-17 4 views
1

Я работаю над большим проектом, в котором я пытаюсь динамически загружать общую библиотеку с помощью QLibrary, я смог воспроизвести ошибка выполнения ссылки (undefined symbol: staticMetaObject) в следующем примере: структураQT QLibrary «Невозможно загрузить библиотеку * .so: (* .so: undefined symbol: staticMetaObject)»

Папка:

root\ 
-- src\ 
---- TestLib\ 
------ TestLib.pro 
------ Derived.h 
------ Derived.cpp 
------ TestLibModuleBridge.h 
------ TestLibModuleBridge.cpp 
---- TestLibCommon\ 
------ IBase.h 
---- TestLibManager\ 
------ TestLibManager.pro 
------ main.cpp 
--lib\ 

TestLib файлы:

# 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 F Ильз:

// 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 Файлы

// 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 

testLib.load() терпит неудачу с Error : "Cannot load library ../../lib/libTestLib.so: (../../lib/libTestLib.so: undefined symbol: _ZN5IBase16staticMetaObjectE)"

Как я могу это исправить, убрав Q_OBJECT от IBase.h исправит ошибку, но в производственном проекте этот интерфейс содержит сигналы и слоты, и это из проекта, который нам не разрешено изменять.

ответ

2

Похоже, что moc не был запущен перед компиляцией тестового листа. moc несет ответственность за создание staticMetaObject для классов, которые содержат Q_OBJECT. Макро и перечислены в разделе HEADERS в профиле.

Добавление TestLibCommon\IBase.h в HEADERS в TestLib.pro должно, вероятно, решить эту проблему. (Непроверенные).


Возможное улучшение вашего решения:
Вместо использования QLibrary взглянуть на QPluginLoader.

QPluginLoader даст вам QObject, который вы можете бросить в любой интерфейс вы хотите использовать qobject_cast<T*>(pluginloader.instance())

Вот пример использования QPluginLoader: http://doc.qt.io/qt-5/qtwidgets-tools-plugandpaint-example.html

Смежные вопросы