如何从 Qt 插件中使用宿主应用程序的类?

Posted

技术标签:

【中文标题】如何从 Qt 插件中使用宿主应用程序的类?【英文标题】:How to use the classes of the host application from a Qt plugin? 【发布时间】:2016-08-24 00:53:43 【问题描述】:

我通过创建 Qt C++ 插件来扩展我的应用程序的功能时遇到了链接问题。代码可以编译并且一切正常,但只要我使用 Qt 库类,例如 QString。当我为插件的类提供对主机应用程序中定义的类中的对象的引用时,该项目不再链接。创建插件 我遵循 Qt 文档中的过程并考虑给定的示例 - echo 和 plug&paint。但是,这种情况不在此列。


更新

这是错误:

myPlugin.obj:-1: error: LNK2019: unresolved external symbol "public: class QString __cdecl myClass::answer(void)const" (?answer@myClass@@QEBA?AVQString@@XZ) 在函数中引用public: 虚拟类 QString __cdecl myPlugin::echo(class myClass *)" (?echo@myPlugin@@UEAA?AVQString@@PEAVmyClass@@@Z)

这是导致它的项目:

plugtest.pro

TEMPLATE = subdirs

SUBDIRS += \
    host \
    plugin

host.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = host
TEMPLATE = app


SOURCES += main.cpp\
        MainWindow.cpp \
    myClass.cpp

HEADERS  += MainWindow.h \
    myClass.h \
    plugInterface.h

FORMS    += MainWindow.ui

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMessageBox>
#include <QPluginLoader>
#include <QDir>
#include "myClass.h"
#include "plugInterface.h"

namespace Ui 
class MainWindow;


class MainWindow : public QMainWindow

    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_button_clicked();

private:
    bool loadPlugin();

    Ui::MainWindow *ui;

    plugInterface *m_interface;

    myClass *m_class;
;

#endif // MAINWINDOW_H

myClass.h

#ifndef MYCLASS_H
#define MYCLASS_H

#include <QObject>

class myClass : public QObject

    Q_OBJECT
public:
    explicit myClass(QObject *parent = 0);

    QString answer() const;
    void setAnswer(const QString &str);

private:
    QString m_answer;
;

#endif // MYCLASS_H

plugInterface.h

#ifndef PLUGINTERFACE_H
#define PLUGINTERFACE_H

#include <QString>
#include "myClass.h"

class plugInterface

public:
    virtual ~plugInterface() 
    virtual QString echo(myClass *value) = 0;
;

#define PlugInterface_iid "example.suite.app.PluginInterface"

Q_DECLARE_INTERFACE(plugInterface, PlugInterface_iid)

#endif // PLUGINTERFACE_H

MainWindow.cpp

#include "MainWindow.h"
#include "ui_MainWindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)

    ui->setupUi(this);

    if (!loadPlugin())
    
        QMessageBox::information(this, "Error", "Could not load the plugin");
    

    m_class = new myClass(this);
    m_class->setAnswer("Good!");


MainWindow::~MainWindow()

    delete ui;


bool MainWindow::loadPlugin()
  
      QDir pluginsDir(qApp->applicationDirPath());

      if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release")
      pluginsDir.cd("plugins");

      foreach (QString fileName, pluginsDir.entryList(QDir::Files))
      
          QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
          QObject *plugin = pluginLoader.instance();
          if (plugin) 
              m_interface = qobject_cast<plugInterface *>(plugin);
              if (m_interface)
                  return true;
          
      

      return false;
  

void MainWindow::on_button_clicked()

    ui->lineResult->setText(m_interface->echo(m_class));

myClass.cpp

#include "myClass.h"

myClass::myClass(QObject *parent) : QObject(parent)




QString myClass::answer() const

    return m_answer;


void myClass::setAnswer(const QString &str)

    m_answer = str;

plugin.pro

  TEMPLATE        = lib
  CONFIG         += plugin
  QT             += widgets
  INCLUDEPATH    += ../host
  HEADERS         = myPlugin.h
  SOURCES         = myPlugin.cpp
  TARGET          = $$qtLibraryTarget(myPlugin)
  DESTDIR         = ../plugins

myPlugin.h

#ifndef MYPLUGIN_H
#define MYPLUGIN_H

#include <QObject>
#include "plugInterface.h"

class myPlugin : public QObject, plugInterface

    Q_OBJECT
    Q_PLUGIN_METADATA(IID "example.suite.app.PluginInterface")
    Q_INTERFACES(plugInterface)

public:
    QString echo(myClass *value) Q_DECL_OVERRIDE;
;

#endif // MYPLUGIN_H

myPlugin.cpp

#include "myPlugin.h"

QString myPlugin::echo(myClass *value)

    return value->answer();

【问题讨论】:

您不认为错误消息可能相关吗? 当然。我将使用代码和错误更新问题。 【参考方案1】:

对我有用的解决方案是使 myClass 成为库的一部分,并将其动态包含在插件和主机中。但是,我很好奇这是否可以在不创建库的情况下完成。

【讨论】:

以上是关于如何从 Qt 插件中使用宿主应用程序的类?的主要内容,如果未能解决你的问题,请参考以下文章

Activity插件化解决方案

如何从基于 QObject 的类方法返回 QList<double> 以在 Qt 脚本中使用

Qt或通用c++如何在c++中获取或检测<a href="file.html" >的宿主

如何从 Qt 插件中获取调试消息?

iOS 单元/应用程序测试目标如何链接到其宿主应用程序中的类?

使用 Mac OS X 应用程序部署 Qt - 如何不加载任何插件?