Export Functions

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

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

Basic Type Mapping

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

C++ TypeD TypePlugify AliasRef Support ?
voidvoidvoid
boolboolbool
charcharchar8
char16_twcharchar16
int8_tbyteint8
int16_tshortint16
int32_tintint32
int64_tlongint64
uint8_tubyteuint8
uint16_tushortuint16
uint32_tuintuint32
uint64_tulonguint64
uintptr_tsize_tptr64
uintptr_tsize_tptr32
floatfloatfloat
doubledoubledouble
void*void*function
plg::stringstringstring
plg::anyVariantany
plg::vector<bool>bool[]bool[]
plg::vector<char>char[]char8[]
plg::vector<char16_t>wchar[]char16[]
plg::vector<int8_t>byte[]int8[]
plg::vector<int16_t>short[]int16[]
plg::vector<int32_t>int[]int32[]
plg::vector<int64_t>long[]int64[]
plg::vector<uint8_t>ubyte[]uint8[]
plg::vector<uint16_t>ushort[]uint16[]
plg::vector<uint32_t>uint[]uint32[]
plg::vector<uint64_t>ulong[]uint64[]
plg::vector<uintptr_t>size_t[]ptr64[]
plg::vector<uintptr_t>size_t[]ptr32[]
plg::vector<float>float[]float[]
plg::vector<double>double[]double[]
plg::vector<plg::string>string[]string[]
plg::vector<plg::any>Variant[]any[]
plg::vector<plg::vec2>Vector2[]vec2[]
plg::vector<plg::vec3>Vector3[]vec3[]
plg::vector<plg::vec4>Vector4[]vec4[]
plg::vector<plg::mat4x4>Matrix4x4[]mat4x4[]
plg::vec2Vector2vec2
plg::vec3Vector3vec3
plg::vec4Vector4vec4
plg::mat4x4Matrix4x4mat4x4

Exporting Functions in D

Exporting functions in D requires wrapping them with the mixin Export directive to create extern(C) functions compatible with Plugify. These functions can then be called by other plugins.

Basic Example

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

Function Definition

plugin.d
module example_plugin;

import plugify.export;

// Export the function using mixin Export
mixin Export!(
    "AddNumbers", // Function name
    int,          // Return type
    [int, int]    // Parameter types
);

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

Plugin Manifest

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

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

Advanced Example: Exporting Complex Functions

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

Function Definition

plugin.d
module example_plugin;

import plugify.export;

// Export the function using mixin Export
mixin Export!(
    "ProcessData", // Function name
    string[],      // Return type
    [double[], string] // Parameter types
);

string[] ProcessData(double[] data, string prefix) {
    /**
     * Processes an array of doubles and returns an array of strings.
     *
     * @param data: Array of double values.
     * @param prefix: Prefix to add to each value.
     * @return: Array of formatted strings.
     */
    return data.map!(value => prefix ~ value.to!string).array;
}

Plugin Manifest

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

Exporting Functions with References

Plugify supports reference parameters that allow functions to modify values and return them to the caller. In D, reference parameters are declared using the ref keyword, which is similar to C++ references.

Function Definition with Reference Parameters

plugin.d
module example_plugin;

import plugify.export;

// Export the function using mixin Export
mixin Export!(
    "IncrementValue", // Function name
    void,             // Return type
    [int]             // Parameter types (ref is specified in function signature)
);

void IncrementValue(ref int value) {
    /**
     * Increments an integer value by reference.
     *
     * @param value: The value to increment (passed by reference).
     */
    value += 1;
}

// Export the function using mixin Export
mixin Export!(
    "Calculate",          // Function name
    void,                 // Return type
    [int, int, int, int]  // Parameter types (ref is specified in function signature)
);

void Calculate(int a, int b, ref int sum, ref int product) {
    /**
     * Calculates sum and product of two numbers, returning both via reference.
     *
     * @param a: First number.
     * @param b: Second number.
     * @param sum: Output parameter for sum (passed by reference).
     * @param product: Output parameter for product (passed by reference).
     */
    sum = a + b;
    product = a * b;
}

Plugin Manifest with Reference Parameters

In the manifest, mark parameters that are passed by reference using "ref": true:

plugin_name.pplugin
{
  "name": "ExampleDPlugin",
  "version": "1.0.0",
  "methods": [
    {
      "name": "IncrementValue",
      "funcName": "IncrementValue_Exported",
      "paramTypes": [
        {
          "type": "int32",
          "name": "value",
          "ref": true
        }
      ],
      "retType": {
        "type": "void"
      }
    },
    {
      "name": "Calculate",
      "funcName": "Calculate_Exported",
      "paramTypes": [
        {
          "type": "int32",
          "name": "a"
        },
        {
          "type": "int32",
          "name": "b"
        },
        {
          "type": "int32",
          "name": "sum",
          "ref": true
        },
        {
          "type": "int32",
          "name": "product",
          "ref": true
        }
      ],
      "retType": {
        "type": "void"
      }
    }
  ]
}

Reference Parameter Support

Reference parameters work with most Plugify types as shown in the "Ref Support" column of the type mapping table. The following types do not support references:

  • void (cannot be passed by reference)
  • function (callback/delegate types)

All other types including primitives, strings, arrays, and structs support reference parameters using D's ref keyword.

Handling Callbacks

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

Function Definition

plugin.d
module example_plugin;

import plugify.export;

// Export the function using mixin Export
mixin Export!(
    "ExecuteWithCallback", // Function name
    void,                  // Return type
    [int, string, void delegate(int, string)] // Parameter types
);

void ExecuteWithCallback(int value, string inputStr, void delegate(int, string) callback) {
    /**
     * Executes a callback function with the provided parameters.
     *
     * @param value: Integer value.
     * @param inputStr: Input string.
     * @param callback: Callback function to execute.
     */
    string result = callback(value, inputStr);
    import std.stdio;
    writeln("Callback result: ", result);
}

Plugin Manifest

plugin_name.pplugin
{
  "name": "ExampleDPlugin",
  "version": "1.0.0",
  "methods": [
    {
      "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 mixin Export: Always use the mixin Export directive to create extern(C) 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 methods section.

Conclusion

Exporting functions in D plugins is straightforward when you follow Plugify's conventions and best practices. By using the mixin 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.