Overview
IronBullet’s plugin system uses a C-compatible FFI interface to load custom blocks from dynamic libraries (.dll files). Plugins can be written in any language that can produce C-compatible exports, though the included examples use Rust.FFI Interface
Plugins must implement four exported functions that match the C ABI defined insrc/plugin/abi.rs:
Required Exports
ABI Structures
PluginInfo
Defines plugin metadata:name- Plugin identifier (e.g., “ExamplePlugin”)version- Semantic version string (e.g., “0.1.0”)author- Author namedescription- Human-readable descriptionblock_count- Number of blocks this plugin provides
BlockInfo
Defines block metadata for UI and execution:block_type_name- Unique identifier in format “PluginName.BlockName”label- Display name shown in UIcategory- Category for block grouping (e.g., “Utilities”, “Bypass”)color- Hex color code for visual identification (e.g., “#9b59b6”)icon- Icon identifier from icon setsettings_schema_json- JSON schema defining configurable settingsdefault_settings_json- JSON object with default setting values
ExecuteResult
Returned byplugin_execute to communicate execution results:
success- Whether execution completed successfullyupdated_variables_json- JSON object with modified/new variableslog_message- Human-readable log messageerror_message- Error description (only ifsuccessis false)
Plugin Lifecycle
1. Loading
ThePluginManager scans a directory for .dll files and loads each plugin:
- Load the dynamic library using
libloading - Call
plugin_info()to get metadata - Call
plugin_block_info(i)for each block (0 toblock_count - 1) - Store metadata and library handle
src/plugin/manager.rs:74-131 for the complete loading implementation.
2. Execution
When a plugin block is executed:- Find the plugin and block by
block_type_name - Serialize settings and variables to JSON
- Call
plugin_execute()with JSON strings - Parse the
ExecuteResult - Free allocated strings using
plugin_free_string() - Return updated variables and log message
src/plugin/manager.rs:141-206 for the execution implementation.
3. Memory Management
Critical: Plugins allocate strings that must be freed by the caller:plugin_free_string as:
Hot-Loading
Plugins can be reloaded by callingscan_directory() again:
Querying Plugins
Get All Plugin Metadata
Get All Block Metadata
Executing Blocks
Thread Safety
PluginManager is marked as Send + Sync:
- The manager can be shared across threads
- Plugins must be thread-safe if called concurrently
- Hot-reloading requires exclusive access (mutable reference)
Error Handling
Plugins return errors via theExecuteResult structure:
Cargo Configuration
Plugins must be compiled as dynamic libraries. InCargo.toml:
plugin.dllon Windowslibplugin.soon Linuxlibplugin.dylibon macOS
.dll files (see manager.rs:65).