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

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

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

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

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

Тип C++Тип GoПсевдоним PlugifyПоддержка Ref?
voidvoid (not used in Go)void
boolboolbool
charbytechar8
char16_trunechar16
int8_tint8int8
int16_tint16int16
int32_tint32int32
int64_tint64int64
uint8_tuint8uint8
uint16_tuint16uint16
uint32_tuint32uint32
uint64_tuint64uint64
uintptr_tuintptrptr64
uintptr_tuintptrptr32
floatfloat32float
doublefloat64double
void*unsafe.Pointerfunction
plg::stringstringstring
plg::anyanyany
plg::vector<bool>[]boolbool[]
plg::vector<char>[]bytechar8[]
plg::vector<char16_t>[]runechar16[]
plg::vector<int8_t>[]int8int8[]
plg::vector<int16_t>[]int16int16[]
plg::vector<int32_t>[]int32int32[]
plg::vector<int64_t>[]int64int64[]
plg::vector<uint8_t>[]uint8uint8[]
plg::vector<uint16_t>[]uint16uint16[]
plg::vector<uint32_t>[]uint32uint32[]
plg::vector<uint64_t>[]uint64uint64[]
plg::vector<uintptr_t>[]uintptrptr64[]
plg::vector<uintptr_t>[]uintptrptr32[]
plg::vector<float>[]float32float[]
plg::vector<double>[]float64double[]
plg::vector<plg::string>[]stringstring[]
plg::vector<plg::any>[]anyany[]
plg::vector<plg::vec2>[]Vector2vec2[]
plg::vector<plg::vec3>[]Vector3vec3[]
plg::vector<plg::vec4>[]Vector4vec4[]
plg::vector<plg::mat4x4>[]Matrix4x4mat4x4[]
plg::vec2Vector2vec2
plg::vec3Vector3vec3
plg::vec4Vector4vec4
plg::mat4x4Matrix4x4mat4x4

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

Экспорт функций в Go требует пометки функций для экспорта с помощью директивы //export. Эти функции затем могут быть вызваны другими плагинами. Языковой модуль Go от Plugify позаботится обо всем остальном.

Использование генератора для упрощения экспорта функций

Инструмент generator.go упрощает процесс экспорта функций Go путем:

  1. Сканирования папки плагина: Он сканирует корневую папку вашего плагина для определения функций для экспорта.
  2. Чтения манифеста: Он читает файл манифеста .pplugin для понимания сигнатур и типов функций.
  3. Генерации файлов: Он генерирует файлы autoexport.go и autoexport.h с необходимым кодом для экспорта функций.

Этот инструмент устраняет необходимость в ручном маршалинге, облегчая разработчикам интеграцию их плагинов на Go в экосистему Plugify.

Простой пример

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

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

plugin.go
package main

import "C"

func AddNumbers(a int32, b int32) int32 {
    /**
     * Складывает два целых числа.
     *
     * @param a: Первое целое число.
     * @param b: Второе целое число.
     * @return: Сумма a и b.
     */
    return a + b
}

func main() {} // Требуется для плагинов на Go

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

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

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

Сгенерированный код

Запустите инструмент generator.go для генерации файлов autoexport.go и autoexport.h. Эти файлы будут обрабатывать маршалинг типов Plugify в типы Go.

autoexport.go
package main

// #include "autoexports.h"
import "C"
import (
    "github.com/untrustedmodders/go-plugify"
    "reflect"
    "unsafe"
)

//export __AddNumbers
func __AddNumbers(a int32, b int32) int32 {
    return AddNumbers(a, b)
}

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

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

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

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

plugin.go
package main

import "C"
import "unsafe"

func ProcessData(data []float64, prefix string) []string {
    /**
     * Обрабатывает массив чисел double и возвращает отформатированную строку.
     *
     * @param data: Массив значений double.
     * @param length: Длина массива.
     * @param prefix: Префикс для добавления к каждому значению.
     * @return: Отформатированная строка.
     */
    result := ""
    for _, value := range data {
        result += fmt.Sprintf("%s%f", prefix, value)
    }

    return result
}

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

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

Сгенерированный код

Запустите инструмент generator.go для генерации файлов autoexport.go и autoexport.h. Эти файлы будут обрабатывать маршалинг типов Plugify в типы Go.

autoexport.go
package main

// #include "autoexports.h"
import "C"
import (
    "github.com/untrustedmodders/go-plugify"
    "reflect"
    "unsafe"
)

//export __ProcessData
func __ProcessData(data *C.PlgVector, prefix *C.PlgString) C.PlgString {
    __result := ProcessData(plugify.GetVectorDataDouble((*plugify.PlgVector)(unsafe.Pointer(data))), plugify.GetStringData((*plugify.PlgString)(unsafe.Pointer(prefix))))
    __return := plugify.ConstructString(__result)
    return *(*C.String)(unsafe.Pointer(&__return))
}

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

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

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

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

plugin.go
package main

import "C"

func ExecuteWithCallback(value int32, inputStr string, callback PlugifyCallback) {
    /**
     * Выполняет функцию обратного вызова с предоставленными параметрами.
     *
     * @param value: Целочисленное значение.
     * @param inputStr: Входная строка.
     * @param callback: Функция обратного вызова для выполнения.
     */
    result := callback(value, inputStr)
    fmt.Printf("Callback result: %s\n", result)
}

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

plugin_name.pplugin
{
  "name": "ExampleGoPlugin",
  "version": "1.0.0",
  "exportedMethods": [
    {
      "name": "ExecuteWithCallback",
      "funcName": "__ExecuteWithCallback",
      "paramTypes": [
        {
          "type": "int32",
          "name": "value"
        },
        {
          "type": "string",
          "name": "inputStr"
        },
        {
          "type": "function",
          "name": "callback",
          "prototype": {
            "name": "ExampleCallback",
            "funcName": "__ExampleCallback",
            "paramTypes": [
              {
                "type": "int32",
                "name": "value"
              },
              {
                "type": "string",
                "name": "inputStr"
              }
            ],
            "retType": {
              "type": "string"
            }
          }
        }
      ],
      "retType": {
        "type": "void"
      }
    }
  ]
}

Сгенерированный код

Запустите инструмент generator.go для генерации файлов autoexport.go и autoexport.h. Эти файлы будут обрабатывать маршалинг типов Plugify в типы Go.

autoexport.go
package main

// #include "autoexports.h"
import "C"
import (
    "github.com/untrustedmodders/go-plugify"
    "reflect"
    "unsafe"
)

//export __ExecuteWithCallback
func __ExecuteWithCallback(value int32, inputStr *C.PlgString, callback unsafe.Pointer) {
    ExecuteWithCallback(value, plugify.GetStringData((*plugify.PlgString)(unsafe.Pointer(inputStr))), plugify.GetDelegateForFunctionPointer(callback, reflect.TypeOf(PlugifyCallback(nil))).(PlugifyCallback))
}

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

Лучшие практики

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

Заключение

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