2015-07-14 3 views
-2

У меня есть приложение в QT 5.4, но когда мне нужно включить новую функциональность, мне нужно перекомпилировать все приложение, это займет некоторое время, мне нужно знать, как создать или изменить мое приложение, чтобы использовать созданные мной плагины.Qt5.4 Как создать приложение, основанное на плагинах?

+0

Вы исследовали тему? –

+0

Скорее всего, вы используете очень медленный компилятор или машину, которая значительно недостаточна для работы, которую вы пытаетесь выполнить. –

+0

Сколько строк кода в вашем проекте? –

ответ

1

Архитектура с плагинами требует бинарных совместимых и стабильных интерфейсов. После того, как у вас есть это, полная перекомпиляция проекта потребует столько же времени, сколько перекомпиляция одного плагина.

Скорее всего, у вас есть взаимозависимости в коде, которые в любом случае не позволяют поддерживать двоичную совместимость - если вы этого не сделали, ваши изменения будут достаточно локализованы, чтобы перекомпиляция касалась только нескольких файлов.

То, что вы пытаетесь сделать, - это решение неправильной проблемы. Исправьте структуру вашего кода, и время вашей перекомпиляции уменьшится. Нет необходимости в плагинах.

0

Существует много альтернатив; популярный состоит из использования разделяемых библиотек, реализующих четко определенный API.

Например. Представьте себе, что это API вы хотите открыть для настройки:

// pluggin_api.hpp 
// This file defines the pluggin interface. 
#pragma once 

extern "C" { // avoid name mangling 

const char* pluggin_name(); 
void foo(int x); 
void bar(int y); 

} 

Тогда ваши пользователи (или самостоятельно) будет осуществлять различные вариации этого API, например:

// pluggin_1.cpp 

#include "pluggin_api.hpp" 
#include <iostream> 

const char* pluggin_name() { 
    return "Pluggin 1"; 
} 

void foo(int x) { 
    std::cout << "2 * x = " << 2 * x << std::endl; 
} 

void bar(int y) { 
    std::cout << " 3 * y = " << 3 * y << std::endl; 
} 

и

// pluggin_2.cpp 

#include "pluggin_api.hpp" 
#include <iostream> 

const char* pluggin_name() { 
    return "Pluggin 2"; 
} 

void foo(int x) { 
    std::cout << "20 * x = " << 20 * x << std::endl; 
} 

void bar(int y) { 
    std::cout << " 30 * y = " << 30 * y << std::endl; 
} 

Эти .cpp-файлы скомпилированы как разделяемые библиотеки; под Linux это выглядит следующим образом:

$ g++ -shared -fPIC -o pluggin_1.so pluggin_1.cpp 
$ g++ -shared -fPIC -o pluggin_2.so pluggin_2.cpp 

Наконец, основное приложение может вызвать различные pluggins от имени:

// main.cpp 

#include <iostream> 
#include <dlfcn.h> // POSIX --- will work on Linux and OS X, but 
        // you'll need an equivalent library for Windows 

void execute_pluggin(const char* name) { 
    // declare the signature of each function in the pluggin -- you 
    // could do this in the header file instead (or another auxiliary 
    // file) 
    using pluggin_name_signature = const char*(*)(); 
    using foo_signature   = void(*)(int); 
    using bar_signature   = void(*)(int); 

    // open the shared library 
    void* handle = dlopen(name, RTLD_LOCAL | RTLD_LAZY); 

    // extract the functions 
    auto fun_pluggin_name = reinterpret_cast<pluggin_name_signature>(dlsym(handle, "pluggin_name")); 
    auto fun_foo = reinterpret_cast<foo_signature>(dlsym(handle, "foo")); 
    auto fun_bar = reinterpret_cast<bar_signature>(dlsym(handle, "bar")); 

    // call them 
    std::cout << "Calling Pluggin: " << fun_pluggin_name() << std::endl; 
    fun_foo(2); 
    fun_bar(3); 

    // close the shared library 
    dlclose(handle); 
} 


int main(int argc, char *argv[]) { 
    for(int k = 1; k < argc; ++k) { 
    execute_pluggin(argv[k]); 
    } 
} 

компилировать и компоновать с dl библиотеки:

$ g++ -o main main.cpp -std=c++14 -ldl 

и (обратите внимание, что перед именем необходимо указать ./, это связано с соглашениями об именах библиотек и маршрутами поиска):

$ ./main ./pluggin_1.so ./pluggin_2.so 
Calling Pluggin: Pluggin 1 
2 * x = 4 
3 * y = 9 
Calling Pluggin: Pluggin 2 
20 * x = 40 
30 * y = 90 

Есть так много деталей, которые я забыл (что наиболее важно для управления ошибками). Я рекомендую вам прочитать книгу API Design for C++, чтобы найти альтернативные идеи (например, использование языка сценариев, использование наследования, использование шаблонов и их сочетание).

Мне нравится метод общей библиотеки, потому что тогда я могу использовать pluggins в других приложениях (например: я могу использовать библиотеку ctypes Python или Matlab's loadlibrary). Я также могу написать pluggin, скажем, в Fortran, а затем перенести его в интерфейс, совместимый с API.

И наконец: обратите внимание, что это не имеет абсолютно никакого отношения к QT (хотя QT может предоставить платформенный независимый загрузчик разделяемой библиотеки, я не знаю). Это всего лишь обычный способ, с помощью которого люди предоставляют привязки для настройки.

0

Документация Qt предоставляет «How To» для создания плагинов для расширения приложения на основе Qt с использованием собственных механизмов Qt. См. http://doc.qt.io/qt-5/plugins-howto.html.

Это говорит о том, что высокоуровневый API и низкоуровневый API. Вас интересует низкоуровневый API.

Смежные вопросы