Использование CMake с Qt5 и Qt плагинами
Я хотел бы избежать использования файлов qmake
и .pro
. Проблема в том, что я не могу заставить cmake
хорошо работать с Qt 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
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})
Тест-плагин-интерфейс.ГЭС
#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
Тест-плагин.ГЭС
#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
Тест-плагин.cpp
#include <QDebug> #include "test-plugin.hpp" void TestPlugin::doSomething() const { qDebug()<< "hot dog!"; }
Главное.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(); } }