Skip to content

Plugins

Matthew Barker edited this page Aug 8, 2026 · 5 revisions

Plugins

Plugins let your mod expose custom functions inside SQL. Register an SQF function, compile a Rust function into a custom build of the extension, or drop a native C shared library into the plugin directory. Each surfaces as a fn_<name>() function you can call from any SELECT, alongside the built-in SQL functions.

1. SQF Functions (Lightest)

Register an SQF function callable from SQL as fn_<name>(). The extension records the name and arg count, then dispatches invocation back to Arma via the RVExtensionRegisterCallback callback (registered by CBA), so your SQF handles the actual evaluation:

// Register: "register_function <name> <argc> <body>" — one space-joined string
"register_function my_func 2 hint _this" call a3sql_fnc_execute;

// Use in SQL — the engine calls back into SQF with the args
_result = ["SELECT fn_my_func('a', 'b') FROM t"] call a3sql_fnc_execute;

The registered body is dispatched to SQF through the callback; if no callback is registered (no CBA), SQF-registered functions return an error.

2. Rust Trait Plugins (extension source)

For functions compiled into the extension itself. This path is for maintainers shipping their own build of the extension. Stock releases do not include third-party Rust plugins. If you are integrating a3sql into your own mod, the SQF functions (section 1) or C ABI plugins (section 3) cover the same need without rebuilding the extension.

For built-in extensions compiled into the DLL:

use a3sql::engine::plugin::{PluginFunction, register_plugin};

register_plugin(
    "my_plugin",
    vec![PluginFunction {
        name: "hello".into(),
        min_args: 1,
        max_args: 1,
        func: |args| {
            let name = args[0].to_string();
            Ok(DbValue::String(format!("Hello, {}!", name)))
        },
    }],
    vec![],
);

Registered at startup via init_builtin_plugins() in engine/plugin.rs. Callable from SQL: SELECT fn_hello('World') FROM t"Hello, World!"

3. C ABI Dynamic Plugins (Full Power)

Shared libraries (.so / .dll) placed in the plugin directory are loaded at runtime.

Writing a plugin

// my_plugin.c
#include "a3sql_plugin.h"

A3SQL_PLUGIN_INIT {
    a3sql_plugin_register_function("my_plugin", "echo", 1, 1);
    return "my_plugin";
}

Building

gcc -shared -o my_plugin.so my_plugin.c -fPIC

Loading

Drop the compiled .so/.dll into a directory and load from SQF:

["plugin_dir @a3sql/plugins"] call a3sql_fnc_execute;

Or load via TCP:

plugin_dir /path/to/plugins

Listing Plugins

_result = ["plugins"] call a3sql_fnc_execute;
// → [0, "OK", [["builtin_echo", ["echo"], []], ["sqf_user", ["my_func"], ["sqf_called"]]]]
//         plugin_name    functions    hooks

C API Reference

See include/a3sql_plugin.h in the repository for the full header.

Function Purpose
a3sql_plugin_init() Required. Entry point, called at load. Returns plugin name.
a3sql_plugin_register_function(name, fn_name, min_args, max_args) Register a SQL function (callable as fn_<name>)

Example

A complete example plugin is at plugins/example/plugin.c in the repository.

Security Note

C ABI plugins have full access to the game process. Only load plugins from trusted sources.

Clone this wiki locally