Экспорт функций

Руководство по экспорту функций из вашего плагина на C++ для использования другими языковыми модулями в Plugify.

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

Базовое сопоставление типов

В следующей таблице перечислены способы представления типов в C++ API:

Тип C++Псевдоним PlugifyПоддержка ссылок ?
voidvoid
boolbool
charchar8
char16_tchar16
int8_tint8
int16_tint16
int32_tint32
int64_tint64
uint8_tuint8
uint16_tuint16
uint32_tuint32
uint64_tuint64
uintptr_tptr64
uintptr_tptr32
floatfloat
doubledouble
void*function
plg::stringstring
plg::anyany
plg::vector<bool>bool[]
plg::vector<char>char8[]
plg::vector<char16_t>char16[]
plg::vector<int8_t>int8[]
plg::vector<int16_t>int16[]
plg::vector<int32_t>int32[]
plg::vector<int64_t>int64[]
plg::vector<uint8_t>uint8[]
plg::vector<uint16_t>uint16[]
plg::vector<uint32_t>uint32[]
plg::vector<uint64_t>uint64[]
plg::vector<uintptr_t>ptr64[]
plg::vector<uintptr_t>ptr32[]
plg::vector<float>float[]
plg::vector<double>double[]
plg::vector<plg::string>string[]
plg::vector<plg::any>any[]
plg::vector<plg::vec2>vec2[]
plg::vector<plg::vec3>vec3[]
plg::vector<plg::vec4>vec4[]
plg::vector<plg::mat4x4>mat4x4[]
plg::vec2vec2
plg::vec3vec3
plg::vec4vec4
plg::mat4x4mat4x4

Экспорт функций в C++

Чтобы экспортировать функцию в плагине на C++, вам необходимо убедиться, что функция видна другим плагинам. Обычно это делается путем пометки функции макросом PLUGIN_API, который обеспечивает экспорт функции при компиляции плагина в виде динамически подключаемой библиотеки (DLL).

Ключевые моменты

  • Статические функции: Экспортируемые функции, как правило, должны быть static, чтобы избежать необходимости в экземпляре объекта для вызова.
  • С-компоновка: Макрос PLUGIN_API не включает автоматически extern "C" для предотвращения искажения имен (name mangling). Мы должны убедиться, что функцию можно найти просто по имени, добавив extern "C".
  • Типы параметров и возвращаемых значений: Используйте нативные типы Plugify (например, plg::string, plg::vector) для бесшовной интеграции.

Генерация макроса PLUGIN_API

Макрос PLUGIN_API генерируется с помощью CMake. Вот как вы можете настроить его в вашем файле CMakeLists.txt:

include(GenerateExportHeader)
generate_export_header(${PROJECT_NAME}
    EXPORT_MACRO_NAME CPPLM_EXPORT
    EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/exports/module_export.h
)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_BINARY_DIR}/exports)

Это генерирует заголовочный файл (module_export.h), который определяет макрос PLUGIN_API. Включите этот заголовочный файл в исходные файлы вашего плагина, чтобы помечать функции для экспорта.

Базовый пример

Вот простой пример экспорта функции в плагине на C++:

Определение функции

plugin.cpp
#include <plugify/plugify.h>
#include "module_export.h" // Include the generated export header

extern "C" PLUGIN_API int32_t AddNumbers_Exported_Name(int32_t a, int32_t b) {
    return a + b;
}

Экспорт функции

Когда плагин будет загружен, функция AddNumbers будет экспортирована и сможет вызываться другими плагинами.

Пример манифеста плагина

Все экспортированные функции должны быть описаны в файле манифеста плагина в разделе exportedMethods. Вот пример манифеста для плагина, который экспортирует функцию AddNumbers:

plugin_name.pplugin
{
  "name": "ExamplePlugin",
  "version": "1.0.0",
  "exportedMethods": [
    {
      "name": "AddNumbers",
      "funcName": "AddNumbers_Exported_Name",
      "paramTypes": [
        {
          "type": "int32",
          "name": "a"
        },
        {
          "type": "int32",
          "name": "b"
        }
      ],
      "retType": {
        "type": "int32"
      }
    }
  ]
}

Продвинутый пример: Экспорт сложных функций

Вот пример экспорта функции со сложными типами параметров и возвращаемого значения:

Определение функции

plugin.cpp
#include <plugify/plugify.h>
#include "module_export.h"

extern "C" PLUGIN_API plg::vector<plg::string> ProcessData_Exported_Name(const plg::vector<double>& data, const plg::string& prefix) {
    plg::vector<plg::string> result;
    for (double value : data) {
        result.push_back(prefix + std::to_string(value));
    }
    return result;
}

Манифест плагина

plugin_name.pplugin
{
  "name": "ExamplePlugin",
  "version": "1.0.0",
  "exportedMethods": [
    {
      "name": "ProcessData",
      "funcName": "ProcessData_Exported_Name",
      "paramTypes": [
        {
          "type": "double[]",
          "name": "data"
        },
        {
          "type": "string",
          "name": "prefix"
        }
      ],
      "retType": {
        "type": "string[]"
      }
    }
  ]
}

Обработка обратных вызовов (callbacks)

Plugify позволяет экспортировать функции, которые принимают обратные вызовы в качестве параметров. Вот пример:

Определение функции

#include <plugify/plugify.h>
#include "module_export.h"

using CallbackFunction = plg::string(*)(int32_t, const plg::string&);

extern "C" PLUGIN_API void ExecuteWithCallback_Exported_Name(int32_t value, const plg::string& input, CallbackFunction callback) {
    plg::string result = callback(value, input);
    // Process the result
}

Манифест плагина

plugin_name.pplugin
{
  "name": "ExamplePlugin",
  "version": "1.0.0",
  "exportedMethods": [
    {
      "name": "ExecuteWithCallback",
      "funcName": "ExecuteWithCallback_Exported_Name",
      "paramTypes": [
        {
          "type": "int32",
          "name": "value"
        },
        {
          "type": "string",
          "name": "input"
        },
        {
          "type": "function",
          "name": "callback",
          "prototype": {
            "name": "ExampleCallback",
            "funcName": "ExampleCallback_Exported_Name",
            "paramTypes": [
              {
                "type": "int32",
                "name": "value"
              },
              {
                "type": "string",
                "name": "input"
              }
            ],
            "retType": {
              "type": "string"
            }
          }
        }
      ],
      "retType": {
        "type": "void"
      }
    }
  ]
}

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

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

Заключение

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