gpt4 book ai didi

c++ - 插件和基类构造函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:51:38 26 4
gpt4 key购买 nike

在 Qt 应用程序中,我声明了一个基类:

class Base:
public QObject {
Q_OBJECT
public:
Base();
virtual ~Base();
virtual void doSomething();
};

c-tor/d-tor 和 doSomething() 在单独的源文件中都有默认实现。此外,我提供了一个抽象接口(interface)来实现 Qt 的插件方案,就像在 Echo Plugin Example 中一样。 .

class Interface {
public:
virtual ~Interface() {}
virtual Base *create() = 0;
};

#define Interface_iid "blag"
Q_DECLARE_INTERFACE(Interface, Interface_iid)

在驻留在共享库中的插件中,libPlugin.so 我从这个基类派生以提供自定义实现:

class Special:
public Base {
Q_OBJECT
public:
Special() { /* Implementation */ }
void doSomething() { /* Implementation */ }
};

最后我也实现了插件接口(interface):

class Q_DECL_EXPORT Plugin:
public QObject,
public Interface {
Q_OBJECT
Q_PLUGIN_METADATA(IID Interface_iid)
Q_INTERFACES(Interface)

public:
Base *create() {
return new Special();
}
};

现在我可以通过 QPluginLoader 加载这个插件并获得对其核心对象的访问权限,它正确地将自己标识为一个 Plugin。但是,当我尝试 ThePlugin::create() Special 对象时,出现链接错误:

symbol lookup error: libPlugin.so: undefined symbol: _ZN4BaseC2Ev

在名称 mangling 下,我想这是指构造派生的 Special 对象时所需的 Base::Base c-tor。

我很想比较,例如QStylePlugin:它基本上做同样的事情,通过抽象接口(interface)返回一些QStyle-派生类。请引用Style Plugin Example .然而我想不同之处在于,在样式插件的情况下,应用程序(提供自定义样式插件)和样式插件本身都链接到提供的公共(public) Qt 库,例如c-tors.

我该如何解决这个问题?如果链接时间优化删除了 c-tors 会发生什么,因为它不知道插件需要它们?

链接问题

当编译和链接插件时,Base:Base() 类的 c-tor 以及 Base::doSomething() 作为未解析的符号出现. c-tor 由 Special::Special() c-tor 调用,当然无法解析。另一个是虚方法

在编译应用程序本身时,它包含基类方法的实现。显然,在加载插件时它们并没有链接在一起。

中南合作中心

/********** Interface.h */

#ifndef INTERFACE_H
#define INTERFACE_H
#include <QtPlugin>
#include "Base.h"

class Interface {
public:
virtual ~Interface() { }
virtual Base *createWorker() = 0;
};


#define Interface_iid "blag"
Q_DECLARE_INTERFACE(Interface, Interface_iid)
#endif

/********** App.pro */
QT += core

TARGET = App
TEMPLATE = app

SOURCES += \
Base.cpp \
App.cpp

HEADERS += \
Base.h \
Interface.h \

/********** Base.h */
#ifndef BASE_H
#define BASE_H
#include <QObject>

class Base:
public QObject {
Q_OBJECT
public:
Base();
virtual ~Base();
virtual void doSomething();
};
#endif

/********** Base.cpp */

#include "Base.h"

Base::Base():
QObject() {

}

Base::~Base() { }
void Base::doSomething() { }

/********** App.cpp */

#include "Interface.h"
#include <QCoreApplication>
#include <QPluginLoader>
#include <QDebug>

int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);

QPluginLoader l("libPlugin.so");
qDebug() << l.load();
qDebug() << l.errorString();

return a.exec();
}

/********** Plugin.pro */
TARGET = Plugin
CONFIG += plugin
TEMPLATE = lib
SOURCES += \
Plugin.cpp \
Special.cpp \

HEADERS += \
Plugin.h \
Special.h \
Interface.h \
Base.h

/********** Special.h */

#ifndef SPECIAL_H
#define SPECIAL_H
#include <QObject>
#include "Base.h"

class Special:
public Base {
Q_OBJECT
public:
Special();
void doSomething();
};
#endif

/********** Special.cpp */
#include "Special.h"

Special::Special():
Base() {

}

void Special::doSomething() { }

/********** Plugin.h */
#ifndef PLUGIN_H
#define PLUGIN_H
#include <QObject>
#include "Interface.h"

class Q_DECL_EXPORT Plugin:
public QObject,
public Interface {
Q_OBJECT
Q_PLUGIN_METADATA(IID Interface_iid)
Q_INTERFACES(Interface)
public:
Base *createWorker();
};
#endif

/********** Plugin.cpp */
#include "Plugin.h"
#include "Special.h"

Base *Plugin::createWorker() {
return new Special();
}

构建:

# Separate files
qmake Plugin.pro && make
qmake App.pro && make
./App

最佳答案

我想我发现了什么问题。我想链接的结构如下:

  • 提供基类实现的主机应用
  • 从该基类继承并重新实现一些方法和/或访问基类成员的插件共享库

这基本上归结为纯 C 中的以下内容:

  • 宿主应用程序,提供一些符号
  • 一个插件共享库,提供了一些符号,想用宿主的一些符号

但是,没有通用的方法来实现后者。主机可以链接 库以使用其功能。这意味着一旦加载了主机本身和库,主机就会获得动态解析为库的方法 stub 。库和主机之间的契约可能是一些带有声明(而不是定义)的头文件。

当库被动态加载到主机的内存中时,库中的符号反过来不会针对主机进行解析。相反,它们没有得到解决。

这正是我在这里看到的。我试图针对想要加载插件的主机应用程序解析基类的功能(我没有在插件中实现)。不工作。

这是-rdynamic是针对ELF的,引用this post .

关于c++ - 插件和基类构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27623244/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com