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

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

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

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

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

Тип C++Тип PythonПсевдоним PlugifyПоддержка ссылок ?
voidNonevoid❌
boolboolbool✅
charstrchar8✅
char16_tstrchar16✅
int8_tintint8✅
int16_tintint16✅
int32_tintint32✅
int64_tintint64✅
uint8_tintuint8✅
uint16_tintuint16✅
uint32_tintuint32✅
uint64_tintuint64✅
uintptr_tintptr64✅
uintptr_tintptr32✅
floatfloatfloat✅
doublefloatdouble✅
void*Callablefunction❌
plg::stringstrstring✅
plg::anyAnyany✅
plg::vector<bool>list[bool]bool[]✅
plg::vector<char>list[str]char8[]✅
plg::vector<char16_t>list[str]char16[]✅
plg::vector<int8_t>list[int]int8[]✅
plg::vector<int16_t>list[int]int16[]✅
plg::vector<int32_t>list[int]int32[]✅
plg::vector<int64_t>list[int]int64[]✅
plg::vector<uint8_t>list[int]uint8[]✅
plg::vector<uint16_t>list[int]uint16[]✅
plg::vector<uint32_t>list[int]uint32[]✅
plg::vector<uint64_t>list[int]uint64[]✅
plg::vector<uintptr_t>list[int]ptr64[]✅
plg::vector<uintptr_t>list[int]ptr32[]✅
plg::vector<float>list[float]float[]✅
plg::vector<double>list[float]double[]✅
plg::vector<plg::string>list[str]string[]✅
plg::vector<plg::any>list[Any]any[]✅
plg::vector<plg::vec2>list[Vector2]vec2[]✅
plg::vector<plg::vec3>list[Vector3]vec3[]✅
plg::vector<plg::vec4>list[Vectpr4]vec4[]✅
plg::vector<plg::mat4x4>list[Matrix4x4]mat4x4[]✅
plg::vec2Vector2vec2✅
plg::vec3Vector3vec3✅
plg::vec4Vector4vec4✅
plg::mat4x4Matrix4x4mat4x4✅

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

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

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

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

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

plugin.py
def add_numbers_exported(a: int, b: int) -> int:
    """
    Складывает два целых числа.

    :param a: Первое целое число.
    :param b: Второе целое число.
    :return: Сумма a и b.
    """
    return a + b

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

Чтобы экспортировать функцию, опишите ее в манифесте плагина в разделе methods:

plugin_name.pplugin
{
  "name": "ExamplePythonPlugin",
  "version": "1.0.0",
  "methods": [
    {
      "name": "add_numbers",
      "funcName": "add_numbers_exported",
      "paramTypes": [
        {
          "type": "int32",
          "name": "a"
        },
        {
          "type": "int32",
          "name": "b"
        }
      ],
      "retType": {
        "type": "int32"
      }
    }
  ]
}

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

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

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

plugin.py
def process_data_exported(data: list[float], prefix: str) -> list[str]:
    """
    Обрабатывает список чисел с плавающей запятой и возвращает список строк.

    :param data: Список значений с плавающей запятой.
    :param prefix: Префикс для добавления к каждому значению.
    :return: Список отформатированных строк.
    """
    return [f"{prefix}{value}" for value in data]

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

plugin_name.pplugin
{
  "name": "ExamplePythonPlugin",
  "version": "1.0.0",
  "methods": [
    {
      "name": "process_data",
      "funcName": "process_data_exported",
      "paramTypes": [
        {
          "type": "float[]",
          "name": "data"
        },
        {
          "type": "string",
          "name": "prefix"
        }
      ],
      "retType": {
        "type": "string[]"
      }
    }
  ]
}

Экспорт функций с параметрами по ссылке

Plugify поддерживает ссылочные параметры в динамически типизированных языках, таких как Python, но они работают иначе, чем в статически типизированных языках. В Python вы не можете напрямую изменять параметры, переданные по ссылке. Вместо этого вы должны вернуть кортеж, где:

  1. Первый элемент: Возвращаемое значение функции (используйте None, если функция возвращает void)
  2. Остальные элементы: Измененные значения для всех ссылочных параметров в порядке их объявления

Определение функции с параметрами по ссылке

plugin.py
def increment_value_exported(value: int) -> tuple[None, int]:
    """
    Увеличивает целочисленное значение на 1.

    :param value: Значение для увеличения.
    :return: Кортеж из (None, измененное_значение).
    """
    return None, value + 1

def calculate_exported(a: int, b: int, sum: int, product: int) -> tuple[None, int, int]:
    """
    Вычисляет сумму и произведение двух чисел, возвращая оба значения через ссылки.

    :param a: Первое число.
    :param b: Второе число.
    :param sum: Выходной параметр для суммы (передается по ссылке).
    :param product: Выходной параметр для произведения (передается по ссылке).
    :return: Кортеж из (None, sum, product).
    """
    calculated_sum = a + b
    calculated_product = a * b
    return None, calculated_sum, calculated_product

def process_and_count_exported(data: list[float], prefix: str, count: int) -> tuple[list[str], int]:
    """
    Обрабатывает данные и возвращает как результат, так и количество.

    :param data: Список значений float.
    :param prefix: Префикс для добавления к каждому значению.
    :param count: Выходной параметр для количества (передается по ссылке).
    :return: Кортеж из (result, count).
    """
    result = [f"{prefix}{value}" for value in data]
    return result, len(data)

Манифест плагина с параметрами по ссылке

В манифесте отметьте параметры, которые должны обрабатываться как ссылки, используя "ref": "ref":

plugin_name.pplugin
{
  "name": "ExamplePythonPlugin",
  "version": "1.0.0",
  "methods": [
    {
      "name": "increment_value",
      "funcName": "increment_value_exported",
      "paramTypes": [
        {
          "type": "int32",
          "name": "value",
          "ref": "ref"
        }
      ],
      "retType": {
        "type": "void"
      }
    },
    {
      "name": "calculate",
      "funcName": "calculate_exported",
      "paramTypes": [
        {
          "type": "int32",
          "name": "a"
        },
        {
          "type": "int32",
          "name": "b"
        },
        {
          "type": "int32",
          "name": "sum",
          "ref": "ref"
        },
        {
          "type": "int32",
          "name": "product",
          "ref": "ref"
        }
      ],
      "retType": {
        "type": "void"
      }
    },
    {
      "name": "process_and_count",
      "funcName": "process_and_count_exported",
      "paramTypes": [
        {
          "type": "float[]",
          "name": "data"
        },
        {
          "type": "string",
          "name": "prefix"
        },
        {
          "type": "int32",
          "name": "count",
          "ref": "ref"
        }
      ],
      "retType": {
        "type": "string[]"
      }
    }
  ]
}

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

  1. Порядок возврата: Первое возвращаемое значение - это фактическое возвращаемое значение функции. Последующие значения соответствуют ссылочным параметрам в порядке их объявления.
  2. Функции с void: Если функция возвращает void, первый элемент кортежа должен быть None.
  3. Смешанные возвраты: Если функция имеет как возвращаемое значение, так и ссылочные параметры, возвращаемое значение идет первым, за ним следуют все ссылочные параметры.
  4. Подсказки типов: Используйте tuple[ReturnType, RefType1, RefType2, ...] для правильных аннотаций типов.

Поддержка параметров по ссылке

Параметры по ссылке работают с большинством типов Plugify, как показано в столбце "Поддержка ссылок" таблицы сопоставления типов. Следующие типы не поддерживают ссылки:

  • void/None (не может быть передан по ссылке)
  • function (типы обратных вызовов)

Все остальные типы, включая примитивы, строки и списки, поддерживают параметры по ссылке через паттерн возврата кортежа.

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

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

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

plugin.py
def execute_with_callback_exported(value: int, input_str: str, callback: callable) -> None:
    """
    Выполняет функцию обратного вызова с предоставленными параметрами.

    :param value: Целочисленное значение.
    :param input_str: Входная строка.
    :param callback: Функция обратного вызова для выполнения.
    """
    result = callback(value, input_str)
    print(f"Callback result: {result}")

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

plugin_name.pplugin
{
  "name": "ExamplePythonPlugin",
  "version": "1.0.0",
  "methods": [
    {
      "name": "execute_with_callback",
      "funcName": "execute_with_callback_exported",
      "paramTypes": [
        {
          "type": "int32",
          "name": "value"
        },
        {
          "type": "string",
          "name": "input_str"
        },
        {
          "type": "function",
          "name": "callback",
          "prototype": {
            "name": "example_callback",
            "funcName": "example_callback_exported",
            "paramTypes": [
              {
                "type": "int32",
                "name": "value"
              },
              {
                "type": "string",
                "name": "input_str"
              }
            ],
            "retType": {
              "type": "string"
            }
          }
        }
      ],
      "retType": {
        "type": "void"
      }
    }
  ]
}

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

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

Заключение

Экспорт функций в плагинах на Python прост и понятен. Определяя ваши функции и описывая их в манифесте плагина, вы можете создавать надежные и совместимые плагины. Для более сложных сценариев использования, таких как обработка обратных вызовов, используйте методы, изложенные в этом руководстве.