我正在开发一个大型项目,我尝试使用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
宏将修复错误但在生产项目中该接口包含信号和插槽,并且它来自项目我们不是允许改变。
答案 0 :(得分:4)
在编译testlib之前,似乎尚未运行moc
。
moc
负责为包含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