Импорт функций

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

Чтобы использовать функции из другого плагина в вашем плагине на C++, вам необходимо сгенерировать специфичные для языка заголовочные файлы. Эти заголовочные файлы предоставляют необходимые обертки для вызова функций, экспортируемых другими плагинами. Это руководство объясняет, как генерировать эти заголовочные файлы и как использовать их в вашем плагине на C++.

Генерация заголовочных файлов

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

Шаги по генерации привязок

Использование онлайн-генератора:

Посетите инструмент plugify-gen для генерации привязок через удобный веб-интерфейс. Просто загрузите файл манифеста плагина (.pplugin) и выберите C++ в качестве целевого языка, чтобы сгенерировать соответствующий модуль.

Использование инструмента командной строки:

Вы также можете скачать и использовать инструмент-генератор локально из репозитория plugify-gen.

Пример использования:

plugify-gen -manifest ./plugins/plugin_from_another_language/plugin_from_another_language.pplugin -output ./output/ -lang cpp

Интегрируйте сгенерированный модуль:

  • Инструмент создаст папку external/plugify/include/plugin_from_another_language/ в указанной выходной директории. В ней заголовки и один исходный файл plugin_from_another_language.cpp, который определяет указатели на функции.
  • Скопируйте сгенерированную папку в свой проект.
  • Добавьте её родительскую папку в пути включения, а файл .cpp в исходники.
  • Укажите плагин в dependencies своего манифеста, чтобы он загружался раньше вашего.

Интеграция с проектом

После генерации модуля интегрируйте его в ваш проект на C++:

Скопируйте модуль в проект

Скопируйте сгенерированную папку в свой проект:

cp -r ./output/external/plugify/include/plugin_from_another_language ./my_plugin/external/plugify/include/

Обновите CMakeLists.txt

Добавьте путь включения и сгенерированный исходный файл:

target_include_directories(${PROJECT_NAME} PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/external/plugify/include
)
target_sources(${PROJECT_NAME} PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/external/plugify/include/plugin_from_another_language/plugin_from_another_language.cpp
)

Включите в исходные файлы

Включите сгенерированный заголовок в ваши исходные файлы:

#include <plugin_from_another_language/plugin_from_another_language.hpp>

Использование сгенерированных функций-оберток

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

Пример сгенерированного заголовочного файла

Вот пример сгенерированного заголовочного файла для плагина с именем plugin_from_another_language:

plugin_from_another_language/core.hpp
#pragma once

#include "enums.hpp"
#include "aliases.hpp"
#include "delegates.hpp"
#include <plugin_export.h>

// Generated from plugin_from_another_language.pplugin (group: core)

namespace plugin_from_another_language {

  using _ParamCallback = void (*)(int32_t, float, double, const plg::vec4&, const plg::vector<int64_t>&, char, const plg::string&, char16_t, int16_t);
}
extern "C" PLUGIN_API plugin_from_another_language::_ParamCallback __plugin_from_another_language_ParamCallback;
namespace plugin_from_another_language {
  inline void ParamCallback(int32_t a, float b, double c, const plg::vec4& d, const plg::vector<int64_t>& e, char f, const plg::string& g, char16_t h, int16_t k) {
    return __plugin_from_another_language_ParamCallback(a, b, c, d, e, f, g, h, k);
  }
} // namespace plugin_from_another_language

Как это работает

  • plugin_from_another_language.cpp определяет указатель __plugin_from_another_language_ParamCallback, изначально nullptr.
  • Когда ваш плагин загружается, языковой модуль C++ находит этот экспортированный указатель в вашей библиотеке и записывает в него адрес экспортированной функции.
  • Функция-обертка (ParamCallback) вызывает функцию через указатель, передавая параметры напрямую.
  • Если сборка использует version script с local: *;, добавьте __plugin_from_another_language_*; в global:. Иначе модуль не увидит указатель, он останется nullptr, и первый вызов приведёт к падению.

Пример: Использование сгенерированного заголовочного файла

Вот как вы можете использовать сгенерированный заголовочный файл в вашем плагине на C++:

plugin.cpp
#include <plugin_from_another_language/plugin_from_another_language.hpp> // Include the generated header

void MyPluginFunction() {
    // Call the exported function from the other plugin
    plugin_from_another_language::ParamCallback(
        42,                // int32_t a
        3.14f,             // float b
        2.718,             // double c
        {1.0f, 2.0f, 3.0f, 4.0f}, // plg::vec4 d
        {100, 200},        // plg::vector<int64_t> e
        'x',               // char f
        "Hello, Plugify!", // plg::string g
        u'✓',              // char16_t h
        10                 // int16_t k
    );
}

Когда необходима генерация заголовочных файлов?

В C++ сгенерированные заголовки нужны для каждого импортируемого плагина, на каком бы языке он ни был написан. Без них компилятор не сможет ссылаться на экспортированные функции. Плагинам на динамически типизированных языках, таких как Python, этот шаг не нужен, поскольку привязка методов происходит во время выполнения.

Рекомендации

  1. Используйте инструмент-генератор: Всегда используйте инструмент-генератор Plugify (онлайн или командной строки) для генерации заголовочных файлов для импортируемых функций.
  2. Включайте сгенерированные заголовочные файлы: Включайте сгенерированные заголовочные файлы в исходные файлы вашего плагина для доступа к экспортированным функциям.
  3. Тщательно тестируйте: Тестируйте импортированные функции, чтобы убедиться, что они работают как ожидалось.
  4. Документируйте зависимости: Четко документируйте плагины и функции, от которых зависит ваш плагин.

Заключение

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