QT QLibrary"无法加载库* .so:(* .so:undefined symbol:staticMetaObject)"

时间:2015-07-17 16:05:07

标签: c++ qt

我正在开发一个大型项目,我尝试使用QLibrary动态加载共享库,我能够在以下示例中重现运行时链接错误(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文件:

// 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宏将修复错误但在生产项目中该接口包含信号和插槽,并且它来自项目我们不是允许改变。

1 个答案:

答案 0 :(得分:4)

在编译testlib之前,似乎尚未运行mocmoc负责为包含staticMetaObject的类生成Q_OBJECT列在专业文件的HEADERS部分下。< / p>

TestLibCommon\IBase.h添加到TestLib.pro中的HEADERS应该可以解决此问题。 (未测试)。

您的解决方案可能有所改进:
而不是使用QLibrary来看看QPluginLoader

QPluginLoader将为您提供QObject,然后您可以使用qobject_cast<T*>(pluginloader.instance())

将其转换为您想要的任何界面

以下是使用QPluginLoader的示例: http://doc.qt.io/qt-5/qtwidgets-tools-plugandpaint-example.html