Import Functions

Learn how to import functions from other plugins written in different languages and use them in your own.

In Plugify, the Lua language module allows you to import and use functions from plugins written in other languages. This is achieved through runtime-generated synthetic modules, which enable seamless inter-plugin communication.

This guide explains how to import functions in Lua.

Overview

When importing functions from another plugin in Lua:

  1. Runtime-Generated Modules: Plugify dynamically generates synthetic modules at runtime, allowing you to import and call functions from other plugins directly.
  2. Direct Function Calls: Functions are called directly using the imported synthetic modules.

Importing Functions in Lua

Import Synthetic Modules

To import functions from another plugin, use Plugify's require system to load the synthetic module for the target plugin.

plugin.lua
local Plugify = require('plugify')
local Vector2, Vector3, Vector4, Matrix4x4 = Plugify.Vector2, Plugify.Vector3, Plugify.Vector4, Plugify.Matrix4x4
local master = require('plugin_from_another_language')
  • plugify: The core Plugify module, providing utility classes like Vector2, Vector3, etc.
  • plugin_from_another_language: The synthetic module for the target plugin. Replace this with the name of the plugin you want to import functions from.

Call the Imported Functions

Once the synthetic module is imported, you can call its functions directly.

Example 1: Calling a Simple Function

plugin.lua
local function func()
    master.ParamCallback(
        111, 
        2.2, 
        5.1234, 
        Vector4:new(-125.1, -225.2, -325.3, -425.4), 
        {60000000, -700000000, 80000000000}, 
        'D', 
        'pink metal', 
        'Y', 
        -100
    )
end

return {
    func = func
}
  • ParamCallback: This is an example function exported by the target plugin. Replace it with the actual function name.
  • Parameters: Pass the required parameters as defined by the function signature.

Example 2: Calling a Function with a Callback Parameter

If the imported function requires a callback as a parameter, you can define the callback in Lua and pass it to the function. Here's an example:

plugin.lua
local CallbackHolder = {
    mockFunc = function(u32, v3, u_vec)
        -- Modify the parameters (passed by reference)
        u32 = 42
        v3 = Vector3:new(1.0, 2.0, 3.0)
        u_vec = {1, 2, 3}
        -- Return the modified values
        return nil, u32, v3, u_vec
    end
}

local function func_call()
    local result = master.CallFuncCallback(CallbackHolder.mockFunc)
    return result
end

return {
    func_call = func_call
}
  • CallFuncCallback: This is an example function that accepts a callback as a parameter.
  • mockFunc: This is the callback function defined in JavaScript. It modifies the parameters passed by reference and returns them in an array.
  • Return Values: The callback function returns null (for the void return type) and the modified parameters.

Using Type Files for Development

While Lua is dynamically typed and does not use type files like TypeScript, you can still benefit from development aids such as auto-complete, documentation, and static analysis by generating helper type hints or documentation for imported plugin APIs.

Generating Type Files

Plugify provides a unified generator tool to automatically generate type files for imported plugins.

Using the Online Generator:

Visit plugify-gen tool to generate type files through a user-friendly web interface. Simply upload your plugin manifest file (.pplugin) and select Lua as the target language to generate the corresponding .lua annotation file.

Using the Command-Line Tool:

You can also download and use the generator tool locally from the plugify-gen repository.

Example usage:

plugify-gen -manifest ./plugins/MyPlugin/MyPlugin.pplugin -output ./types/ -lang lua

Generated Type File:

  • The script will generate a lua file (e.g., MyPlugin.lua) in the specified output folder.
  • Example type file content:
    MyPlugin.lua
    ---@param a integer
    ---@param b number
    ---@param c number
    ---@param d Vector4
    ---@param e integer[]
    ---@param f string
    ---@param g string
    ---@param h string
    ---@param k integer
    function ParamCallback(a, b, c, d, e, f, g, h, k) end
    
    ---@alias Func fun(u32: integer, vec3: Vector3, vecU32: integer[]): nil, integer, Vector3, integer[]
    
    ---@param callback Func
    ---@return string
    function CallFuncCallback(callback) end
    

Using Type Files in Your IDE:

  • Place the generated type file (.lua) in your project directory (but not in the plugins folder).
  • IDEs like VSCode will use the type file to provide type hints and autocompletion.

VSCode Support:

  • VSCode automatically detects type files in your project. Ensure the types folder (or the folder containing your .lua files) is included in your luaconfig.json file.
  • Example luaconfig.json configuration:
    {
        "compilerOptions": {
            "typeRoots": ["./types"]
        }
    }
    

Notes

  • Type Files Are Optional: Type files are only for development and should not be included in your plugin's runtime folder.
  • Runtime Efficiency: Since Lua is dynamically typed, function calls are resolved at runtime without the need for pre-compiled headers or type definitions.

By following this guide, you can easily import and use functions from other plugins in your Lua plugin, while leveraging type files for a better development experience.