QT5, как получить «ссылку» на слоты низкоуровневого API-плагина для использования его в другом низкоуровневом API-плагине? - PullRequest
0 голосов
/ 28 января 2020

У меня есть приложение QT5, которое можно расширить с помощью плагинов приложений с помощью низкоуровневого API плагинов QT5. Пока я могу загрузить / запустить / остановить / выгрузить плагин. Я также могу подключить пользовательский интерфейс плагина к приложению.

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

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

class Task : public QObject
{
public:
     explicit Task( // parameters of task
                      );
     ~Task();

     // methods of Task

signals:
     void succeeded(Task *task);
     void failed(Task *task);

private:
    // some private stuff
}

Таким образом, путь к потребителю, похоже, готов. Теперь мне нужно передать объект «задача» сервис-провайдеру, который находится в другом плагине.

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

class PluginService
{
public:
    explicit PluginService(QObject *service);
    ~PluginService();

    // methods for requesting a service and it's provided slots
    QObject *service();
    QMetaMethod *slot(const QString &slot = "");

    // method to setup the slots for a service
    void addSlot(const QString& name = "", QMetaMethod *slot = nullptr);

private:
    QObject *mService;
    QMap<QString, QMetaMethod *> *mSlots;
};

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

I для получения слотов, как показано ниже в плагине service-provder-plugin:

    // this code is already working as expected
    TaskManager *manager = mForm->taskManager();
    manager->moveToThread(&mThread);

    connect(this, &PluginCmdBase::execute, manager, &TaskManager::onExecute);
    connect(this, &PluginCmdBase::abort, manager, &TaskManager::onAbort);

    mThread.start();

    // here my problems start 
    mServices = new std::vector<pluginbase::PluginService *>();
    pluginbase::PluginService *service = new pluginbase::PluginService(manager);

    // here should the "magic" happen, but I fail to get a proper cast
    service->addSlot("onExecute", &TaskManager::onExecute);
    service->addSlot("onAbort", &TaskManager::onAbort);

    mServices->push_back(service);

"addSlot" явно не работает . Я пробовал разные приведения, но не работал. Я всегда получаю ошибки компилятора, такие как:

Error: no matching function for call to 'pluginbase::PluginService::addSlot(const char [10], void (plugincmd::TaskManager::*)(plugincmd::Task*))'
         service->addSlot("onExecute", &TaskManager::onExecute);
                                                              ^

Я пытался с QMetaMethod, потому что он используется в методе "QObject :: connect ()", но я открыт, чтобы изменить это при необходимости.

Однако как правильно получить «ссылку» на слот поставщика услуг, чтобы я мог использовать его в методе «Object :: connect ()»?

...