【问题标题】:Using CMake with Qt5 and Qt Plugins将 CMake 与 Qt5 和 Qt 插件一起使用
【发布时间】:2015-08-18 03:57:12
【问题描述】:

我想避免使用qmake.pro 文件。问题是我无法让cmakeQt Plugins 很好地合作。我已经包含下面的代码,显示了对给定的.pro 文件正常工作的接口、插件、加载程序,但我不知道如何将此功能转移到cmake

插件接口

加载程序知道的纯虚拟接口。

#include <QtCore/qglobal.h>

class HelloPluginInterface
{
public:
    virtual void DoSomething() const = 0;
};

Q_DECLARE_INTERFACE( HelloPluginInterface, "com.harbrick.Qt.HelloPluginInterface")

插件

成为.so 的插件将被加载程序加载。

#include <QtPlugin>
#include "helloplugin_global.h"

class HelloPlugin : public QObject, public HelloPluginInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA( IID "com.harbrick.Qt.HelloPluginInterface" )
    Q_INTERFACES( HelloPluginInterface )

public:
    void DoSomething() const;
};

插件加载器

void MainWindow::LoadPlugin( const QString& pathToLibrary )
{
    QPluginLoader loader( pathToLibrary );
    QObject* instance = loader.instance();

    if( instance )
    {
        HelloPluginInterface *plugin = qobject_cast< HelloPluginInterface* >( instance );
        if(plugin)
        {
            //do stuff
            ...
        }
        else
        {
            qDebug() << "Not a plugin: " << Filename << " = " << loader.errorString();
        }
    }
}

CMakeLists.txt

无法上班

project( HelloPlugin )
cmake_minimum_required( VERSION 2.8.11 )

set( CMAKE_INCLUDE_CURRENT_DIR ON )

find_package(Qt5Widgets)

include_directories( 
    ${CMAKE_CURRENT_SOURCE_DIR} 
)

set( INCLUDE
    cmakeplugin.h
    cmakeplugininterface.h
)

set( SOURCES
    cmakeplugin.cpp
)

add_executable(${PROJECT_NAME} ${INCLUDE} ${SOURCES} ${SRC_LIST})

add_library( cmakePlugin SHARED cmakeplugin.cpp )

QMake .pro

作品

QT       += widgets

TARGET = HelloPlugin
TEMPLATE = lib

SOURCES += helloplugin.cpp

HEADERS += helloplugin.h \
    helloplugin_global.h

CONFIG += plugin debug

INSTALLS += target

【问题讨论】:

  • “无法开始工作”您会遇到哪些错误?
  • “不是库”加载。我已经想通了,将发布解决方案。
  • @DaveyLaser 似乎是一个非常复杂的解决方案,因为您需要花费数年时间才能发布它。 ;)
  • 哇@Nobody,哈哈!感谢您指出这一点,我会在未来几年的某个时候发布解决方案。

标签: c++ qt cmake qt5 qmake


【解决方案1】:

Qt 为插件生成元代码,在CMakeLists.txt 中添加以下内容:

set(CMAKE_AUTOMOC ON)

这是一个完整的工作示例:

CMakeLists.txt

project(test-plugin)
cmake_minimum_required(VERSION 3.2.0)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)

find_package(Qt5Widgets REQUIRED)

set(COMPILE_OPTIONS -std=c++11)

add_library(test-plugin SHARED test-plugin.cpp)
target_link_libraries(test-plugin PRIVATE Qt5::Widgets)
target_compile_options(test-plugin PRIVATE ${COMPILE_OPTIONS})

add_executable(test-plugin-exec main.cpp)
target_link_libraries(test-plugin-exec PRIVATE Qt5::Widgets)
target_compile_options(test-plugin-exec PRIVATE ${COMPILE_OPTIONS})

test-plugin-interface.hpp

#ifndef TEST_PLUGIN_INTERFACE
#define TEST_PLUGIN_INTERFACE
#include <QtPlugin>

class TestPluginInterface
{
public:
    virtual ~TestPluginInterface() {}
    virtual void doSomething() const = 0;
};

#define TestPluginInterface_iid "whatever.you.want.TestPluginInterface"
Q_DECLARE_INTERFACE(TestPluginInterface, TestPluginInterface_iid)
#endif // TEST_PLUGIN_INTERFACE

test-plugin.hpp

#ifndef TEST_PLUGIN_HPP
#define TEST_PLUGIN_HPP
#include <QObject>
#include <QtPlugin>
#include "test-plugin-interface.hpp"

class TestPlugin : public QObject, public TestPluginInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID TestPluginInterface_iid)
    Q_INTERFACES(TestPluginInterface)

public:
    ~TestPlugin() override {}
    void doSomething() const override;
};
#endif // TEST_PLUGIN_HPP

test-plugin.cpp

#include <QDebug>
#include "test-plugin.hpp"

void TestPlugin::doSomething() const
{
    qDebug()<< "hot dog!";
}

ma​​in.cpp

#include <assert.h>
#include <QDebug>
#include <QPluginLoader>
#include "test-plugin.hpp"

constexpr auto ABSOLUTE_PATH_TO_PLUGIN = 
    "/path/to/build/libtest-plugin.so";

int main(int argc, char* argv[])
{
    assert(QLibrary::isLibrary(ABSOLUTE_PATH_TO_PLUGIN));
    QPluginLoader loader(ABSOLUTE_PATH_TO_PLUGIN);
    if (auto instance = loader.instance()) {
        if (auto plugin = qobject_cast< TestPluginInterface* >(instance)){
            plugin->doSomething();
        }
        else {
            qDebug()<< "qobject_cast<> returned nullptr";
        }
    }
    else {
      qDebug()<< loader.errorString();
    }
}

【讨论】:

  • 谢谢!我拥有所有代码,但缺少 MOC 选项。检查与nm 的区别发现了两个附加功能:qt_plugin_instanceqt_plugin_query_metadata
  • 接口是否需要是同一个类,还是只能是两个看起来一样的类?我之所以问,是因为我正在考虑将插件放在一个单独的项目中,然后是使用该插件的项目,这样它们就不能共享相同的接口文件。
  • 是的,这行得通,界面只需要看起来相似并且具有相同的 iid。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
  • 2017-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-30
相关资源
最近更新 更多