Export Functions

Guide to export functions from your plugin to be used by other language modules within Plugify.

In the Plugify ecosystem, Go plugins can export functions to make them accessible to other plugins. This guide explains how to define and export functions in Go and provides examples to help you integrate your plugins seamlessly.

Basic Type Mapping

The following table lists how types are exposed to the JavaScript API:

C++ TypeGo TypePlugify AliasRef Support ?
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::anyinterface{}any
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>interface{}any
plg::vector<plg::vec2>C.Vector2vec2
plg::vector<plg::vec3>C.Vector3vec3
plg::vector<plg::vec4>C.Vector4vec4
plg::vector<plg::mat4x4>C.Matrix4x4mat4x4
plg::vec2C.Vector2vec2
plg::vec3C.Vector3vec3
plg::vec4C.Vector4vec4
plg::mat4x4C.Matrix4x4mat4x4

Exporting Functions in Go

Exporting functions in Go requires marking the functions for export using the //export directive. These functions can then be called by other plugins. Plugify's Go Language Module handles the rest.

Basic Example

Here’s a simple example of exporting a function in a Go plugin:

Function Definition

plugin.go
package main

import "C"

//export AddNumbers_Exported
func AddNumbers(a C.int, b C.int) C.int {
    /**
     * Adds two integers.
     *
     * @param a: First integer.
     * @param b: Second integer.
     * @return: Sum of a and b.
     */
    return a + b
}

func main() {} // Required for Go plugins

Plugin Manifest

To export the function, describe it in the plugin manifest under the exportedMethods section:

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

Parameter and Return Type Conventions

Plugify uses specific conventions for parameter and return types to ensure compatibility across plugins. Below are the guidelines for Go:

1. Primitive Types

  • Parameter: Pass primitive types (e.g., int, float64) using their corresponding C types (e.g., C.int, C.double).
  • Return: Return primitive types using their corresponding C types.

2. Strings

  • Parameter: Pass strings as *C.PlgString by reference.
  • Return: Return strings as C.PlgString by value.

3. Arrays

  • Parameter: Pass arrays as *C.PlgVector by reference.
  • Return: Return arrays as C.PlgVector by value.

4. Structures

  • Parameter: Pass structures by reference (e.g., *C.struct_MyStruct).
  • Return: Return structures by value.

Advanced Example: Exporting Complex Functions

Here’s an example of exporting a function with complex parameter and return types:

Function Definition

plugin.go
package main

import "C"
import "unsafe"

//export ProcessData_Exported
func ProcessData(data *C.PlgVector, prefix *C.PlgString) C.PlgString {
    /**
     * Processes an array of doubles and returns a formatted string.
     *
     * @param data: Array of double values.
     * @param length: Length of the array.
     * @param prefix: Prefix to add to each value.
     * @return: Formatted string.
     */
    goData := C.GoSlice(data)
    goPrefix := C.GoString(prefix)

    result := ""
    for _, value := range goData {
        result += fmt.Sprintf("%s%f", goPrefix, value)
    }

    return C.PlgString(result)
}

Plugin Manifest

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

Handling Callbacks

Plugify allows you to export functions that accept callbacks as parameters. Here’s an example:

Function Definition

plugin.go
package main

import "C"

//export ExecuteWithCallback_Exported
func ExecuteWithCallback(value C.int, inputStr *C.PlgString, callback C.PlugifyCallback) {
    /**
     * Executes a callback function with the provided parameters.
     *
     * @param value: Integer value.
     * @param inputStr: Input string.
     * @param callback: Callback function to execute.
     */
    goInputStr := C.GoString(inputStr.data)
    result := callback(value, inputStr)
    fmt.Printf("Callback result: %s\n", C.GoString(result.data))
}

Plugin Manifest

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

Best Practices

  1. Use //export: Always use the //export directive to mark functions for export.
  2. Follow Type Conventions: Adhere to Plugify's type conventions for parameters and return values.
  3. Document Your Functions: Clearly document the purpose, parameters, and return values of exported functions.
  4. Test Thoroughly: Test your exported functions to ensure they work as expected when called by other plugins.
  5. Update the Manifest: Always describe exported functions in the plugin manifest under the exportedMethods section.

Conclusion

Exporting functions in Go plugins is straightforward when you follow Plugify's conventions and best practices. By using the //export directive, adhering to type conventions, and describing functions in the plugin manifest, you can create robust and interoperable plugins. For more advanced use cases, such as handling callbacks, use the techniques outlined in this guide.