rustbridge
[!NOTE] This project is in beta. The core API is stable, but some features may change before 1.0.
A framework for developing Rust shared libraries callable from other languages. Uses C ABI under the hood but abstracts the complexity, providing OSGI-like lifecycle, mandatory async (Tokio), logging callbacks, and JSON-based data transport with optional binary transport for performance-critical paths.
The .rbp Bundle
rustbridge plugins are distributed as .rbp (rustbridge plugin) bundles - portable ZIP archives containing:
- Multi-platform libraries - Native libraries for all target platforms in one file
- Manifest - Plugin metadata, version info, and SHA256 checksums
- Optional signatures - Minisign code signing for production security
- Optional schemas - JSON Schema and C headers for API documentation
# Create a bundle
# Load from any language - auto-detects platform
)
See docs/BUNDLE_FORMAT.md for the complete specification.
Overview
rustbridge lowers the barrier for creating Rust plugins that can be loaded and called from Java, C#, Python, and other languages. Instead of manually managing FFI complexity, you implement a simple Plugin trait and rustbridge handles:
- Memory management: Safe buffer allocation and deallocation across FFI boundary
- Async runtime: Tokio runtime included in every plugin
- Lifecycle management: OSGI-inspired state machine (Installed → Starting → Active → Stopping → Stopped)
- Logging: Tracing integration with callbacks to host language
- Serialization: JSON-based message transport with typed envelopes
Features
- Cross-language interoperability: Call Rust code from Java, Kotlin, C#, Python, and more
- Multiple JVM implementations: FFM for Java 21+ (modern, fast) and JNI for Java 17+ (compatibility)
- Kotlin-friendly: Idiomatic Kotlin usage with data classes, extension functions, and type-safe DSL
- JSON-based transport: Simple, universal data serialization
- OSGI-inspired lifecycle: Structured plugin startup and shutdown
- Async-first: Built on Tokio with mandatory async runtime
- FFI logging: Tracing integration with host language callbacks
- Type-safe macros: Procedural macros for reduced boilerplate
- CLI tooling: Project scaffolding and code generation
Project Structure
rustbridge/
├── Cargo.toml # Workspace root
├── crates/
│ ├── rustbridge-core/ # Core traits, types, lifecycle
│ ├── rustbridge-transport/ # JSON codec, message envelopes
│ ├── rustbridge-ffi/ # C ABI exports, buffer management
│ ├── rustbridge-jni/ # JNI bindings for Java 17+
│ ├── rustbridge-runtime/ # Tokio integration
│ ├── rustbridge-logging/ # Tracing → FFI callback bridge
│ ├── rustbridge-macros/ # Procedural macros
│ ├── rustbridge-bundle/ # .rbp bundle creation and parsing
│ └── rustbridge-cli/ # Build tool and CLI
├── rustbridge-java/ # Java/Kotlin bindings
│ ├── rustbridge-core/ # Core interfaces
│ ├── rustbridge-ffm/ # FFM implementation (Java 21+)
│ └── rustbridge-kotlin/ # Kotlin extensions
├── rustbridge-csharp/ # C# bindings (.NET 8.0+)
├── rustbridge-python/ # Python bindings (3.10+)
├── examples/
│ ├── hello-plugin/ # Example Rust plugin
│ └── kotlin-examples/ # Kotlin usage examples
├── docs/
│ ├── ARCHITECTURE.md # System architecture
│ ├── SKILLS.md # Development best practices
│ ├── TESTING.md # Testing conventions
│ └── TASKS.md # Project roadmap
└── CLAUDE.md # Project instructions for Claude Code
Quick Start
📖 New to rustbridge? See the complete Getting Started guide for a step-by-step tutorial.
Creating a Plugin (Rust)
use async_trait;
use ;
use ;
use ;
// Define message types
// Implement the plugin
;
// Generate FFI entry point
rustbridge_entry!;
// Re-export FFI functions
pub use ;
Using from Java (FFM, Java 21+)
;
;
;
try
Using from Java (JNI, Java 17+)
;
;
try
Using from Kotlin
import com.rustbridge.ffm.FfmPluginLoader
// Data classes for type-safe requests
data class EchoRequest(val message: String)
data class EchoResponse(val message: String, val length: Int)
// Extension function for typed calls
inline fun <reified T> Plugin.callTyped(messageType: String, request: Any): T {
val mapper = ObjectMapper()
val responseJson = call(messageType, mapper.writeValueAsString(request))
return mapper.readValue(responseJson, T::class.java)
}
// Use block for automatic cleanup
FfmPluginLoader.load("libmyplugin.so").use { plugin ->
val response = plugin.callTyped<EchoResponse>("echo", EchoRequest("Hello!"))
println(response.message)
}
See examples/kotlin-examples for complete examples.
FFI API
The following C functions are exported by plugins:
// Create plugin instance (called by plugin_init internally)
void* ;
// Initialize plugin with config and optional log callback
void* ;
// Make a synchronous request
FfiBuffer ;
// Free a buffer returned by plugin_call
void ;
// Shutdown the plugin
bool ;
// Set log level (0=Trace, 1=Debug, 2=Info, 3=Warn, 4=Error, 5=Off)
void ;
// Get current lifecycle state
uint8_t ;
// Get count of rejected requests (due to concurrency limit)
uint64_t ;
// Async API (placeholder for future - returns 0/false)
uint64_t ;
bool ;
FfiBuffer Structure
typedef struct FfiBuffer;
Lifecycle States
Installed → Starting → Active → Stopping → Stopped
↑ │
└────────────────────┘ (restart)
Any state → Failed (on error)
| State | Description |
|---|---|
Installed |
Plugin created but not initialized |
Starting |
Initializing runtime, resources |
Active |
Ready to handle requests |
Stopping |
Graceful shutdown in progress |
Stopped |
Shutdown complete |
Failed |
Error occurred |
Building
# Build all crates
# Build in release mode
# Build a specific plugin
# Run tests
# Build CLI tool
CLI Usage
# Create a new plugin project
# Build a plugin
# Generate JSON Schema from Rust message types
# Validate manifest
# Create a bundle for distribution
# Generate signing keys
Configuration
Plugin Configuration (PluginConfig)
Configuration Options:
worker_threads(optional): Number of async worker threads (default: number of CPU cores)log_level: Initial log level - "trace", "debug", "info", "warn", "error", "off" (default: "info")max_concurrent_ops: Maximum concurrent requests (default: 1000)- Set to
0for unlimited (use with caution - can cause memory exhaustion) - Requests exceeding this limit are immediately rejected with error code 13 (TooManyRequests)
- Monitor rejected requests using
plugin.getRejectedRequestCount()(Java) orhandle.rejected_request_count()(Rust)
- Set to
shutdown_timeout_ms: Maximum milliseconds to wait during shutdown (default: 5000)data(optional): Plugin-specific configuration data (JSON object)
Example: Configuring concurrency limits in Java:
PluginConfig config ;
try
Project Manifest (rustbridge.toml)
The rustbridge.toml file is a development-time configuration used by CLI tools for validation, code generation, and bundle creation. It is not included in .rbp bundles directly - bundles contain a separate manifest.json file (see docs/BUNDLE_FORMAT.md for the bundle manifest schema).
[]
= "my-plugin"
= "1.0.0"
= "My awesome plugin"
= ["Your Name"]
[]
= "Create a new user"
= "schemas/CreateUserRequest.json"
= "schemas/CreateUserResponse.json"
[]
= "Delete a user"
[]
= "libmyplugin.so"
= "libmyplugin.so"
= "libmyplugin.dylib"
= "libmyplugin.dylib"
= "myplugin.dll"
Error Handling
Errors are represented with stable numeric codes:
| Code | Error Type |
|---|---|
| 0 | Success |
| 1 | Invalid State |
| 2 | Initialization Failed |
| 3 | Shutdown Failed |
| 4 | Config Error |
| 5 | Serialization Error |
| 6 | Unknown Message Type |
| 7 | Handler Error |
| 8 | Runtime Error |
| 9 | Cancelled |
| 10 | Timeout |
| 11 | Internal Error |
| 12 | FFI Error |
| 13 | Too Many Requests (concurrency limit exceeded) |
Target Languages
| Language | Status | Implementation |
|---|---|---|
| Java/Kotlin | Tier 1 | FFM (Java 21+, recommended) + JNI (Java 17+) |
| C# | Tier 2 | P/Invoke (.NET 8.0+) |
| Python | Tier 2 | ctypes (Python 3.10+) |
Documentation
Getting Started
- docs/GETTING_STARTED.md - Tutorial for creating your first plugin
- docs/using-plugins/JAVA_FFM.md - Java 21+ FFM guide
- docs/using-plugins/JAVA_JNI.md - Java 17+ JNI guide
- docs/using-plugins/KOTLIN.md - Kotlin guide
- docs/using-plugins/CSHARP.md - C# guide
- docs/using-plugins/PYTHON.md - Python guide
Architecture & Design
- docs/ARCHITECTURE.md - System architecture and design decisions
- docs/BUNDLE_FORMAT.md - .rbp bundle specification
- docs/TRANSPORT.md - JSON and binary transport layer
- docs/MEMORY_MODEL.md - Memory ownership patterns
Development
- docs/SKILLS.md - Development best practices and coding conventions
- docs/TESTING.md - Testing conventions and guidelines
- docs/ERROR_HANDLING.md - Error handling patterns
- docs/DEBUGGING.md - Debugging techniques
Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Quick start:
- Read docs/SKILLS.md for coding conventions
- Read docs/TESTING.md for testing guidelines
- Check docs/TASKS.md for open tasks
Changelog
See CHANGELOG.md for version history and release notes.
License
MIT OR Apache-2.0
Attribution
This project includes software licensed under the Unicode License (Unicode-3.0). See NOTICES for details.