我正在处理一个大项目,在这个项目中,我试图用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 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_HtestLib.load()与Error : "Cannot load library ../../lib/libTestLib.so: (../../lib/libTestLib.so: undefined symbol: _ZN5IBase16staticMetaObjectE)"一起失败
如何解决这个问题,从Q_OBJECT宏中删除IBase.h将修复错误,但是在生产项目中,接口包含信号和插槽,而且它来自一个我们不允许更改的项目。
发布于 2015-07-17 20:11:32
在编译testlib之前,似乎还没有运行moc。moc负责为包含Q_OBJECT、宏、和的类生成pro文件中的HEADERS部分。
将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的示例
https://stackoverflow.com/questions/31480066
复制相似问题