ring-lang-rs
Rust bindings for the Ring programming language.
Use Cases
- Write Ring extensions in Rust - Create native extensions with Rust's safety and performance
- Embed Ring in Rust applications - Run Ring scripts from your Rust programs
- Wrap Rust crates for Ring - Expose any Rust library to Ring applications
How It Works
flowchart LR
subgraph ext["<b>Extensions</b>"]
direction LR
A["Ring Program<br/><code>.ring</code>"] -->|"loadlib()"| B["Rust Extension<br/><code>.dll/.so/.dylib</code>"]
B -->|"return values"| A
end
subgraph emb["<b>Embedding</b>"]
direction LR
C["Rust Application<br/><code>binary</code>"] -->|"ring_state_*()"| D["Ring VM<br/><code>embedded</code>"]
D -->|"results"| C
end
Code Generation Tools
Two approaches to generate Ring extensions from Rust code:
| Approach | Location | Best For |
|---|---|---|
| Proc Macro | macros/ |
New projects, pure Rust workflow |
| Ring Script | tools/codegen/ |
Similar to C/C++ Ring codegen workflow |
Proc Macro (ring_extension!) - Zero config, just cargo build:
ring_extension!
Ring Script (parsec.ring) - Uses .rf config files:
Both generate the same Ring-callable functions. See each README for details.
Using Extensions
If you have a Rust extension (.dll/.so/.dylib), using it is simple:
# Load the library (OS-specific)
if iswindows()
loadlib("myextension.dll")
elseif ismacosx()
loadlib("libmyextension.dylib")
else
loadlib("libmyextension.so")
ok
# Call functions just like native Ring functions
? rust_hello() # Hello from Rust!
? rust_add(10, 20) # 30
? rust_greet("Ring") # Hello, Ring!
That's it! No Rust knowledge required.
Creating Extensions
The rest of this document covers how to create Ring extensions in Rust or embed Ring in Rust applications.
Supported Platforms
| Platform | Static | Dynamic | Architectures |
|---|---|---|---|
| Linux | ✅ | ✅ | x86_64, ARM64, ARMv7, RISC-V |
| macOS | ✅ | ✅ | x86_64, ARM64 (Apple Silicon) |
| Windows | ✅ | ✅ | x86_64, x86 (MSVC & GNU) |
| FreeBSD | ✅ | ✅ | x86_64, ARM64 |
| Android | ✅ | - | ARM64, ARMv7, x86_64, x86 |
| WASM (WASI/Emscripten) | ✅ | - | wasm32 |
Other Unix-like systems (OpenBSD, NetBSD, DragonFly BSD, Solaris, etc.) are supported via the generic Unix build path. Any target supported by Rust's std and LLVM should work.
Requirements
- Rust (stable)
- Ring language installed
Installation
Add to your Cargo.toml:
[]
= ["cdylib"]
[]
= "0.1"
Or clone and use locally:
Environment Variables
Optional: Set RING (or ring) to your Ring installation directory:
# Linux/macOS
# Windows (PowerShell)
# Windows (CMD)
If not set, the system's libring will be used.
Quick Start
Extension example:
Embedding example:
Basic Function
use *;
ring_func!;
ring_libinit!
Working with Numbers
ring_func!;
Working with Strings
ring_func!;
Working with Lists
ring_func!;
ring_func!;
Working with C Pointers (Rust Structs)
use c_void;
const MY_TYPE: & = b"MyStruct\0";
ring_func!;
ring_func!;
Managed Pointers (Auto-freed by Ring GC)
extern "C"
ring_func!;
Available Macros
| Macro | Description |
|---|---|
ring_libinit! |
Register functions with Ring |
ring_func! |
Define a Ring function with boilerplate |
ring_check_paracount! |
Validate parameter count |
ring_check_paracount_range! |
Validate parameter count within range |
ring_check_string! |
Validate string parameter |
ring_check_number! |
Validate number parameter |
ring_check_list! |
Validate list parameter |
ring_check_pointer! |
Validate pointer parameter |
ring_check_cpointer! |
Validate C pointer parameter |
ring_get_string! |
Get string parameter |
ring_get_number! |
Get number parameter (f64) |
ring_get_int! |
Get integer parameter (i32) |
ring_get_list! |
Get list parameter |
ring_get_pointer! |
Get typed pointer as Option<&mut T> |
ring_get_cpointer! |
Get raw C pointer |
ring_new_list! |
Create new list |
ring_ret_number! |
Return number |
ring_ret_string! |
Return string |
ring_ret_list! |
Return list |
ring_ret_cpointer! |
Return C pointer |
ring_ret_managed_cpointer! |
Return managed C pointer |
ring_error! |
Raise Ring error |
Module Structure
| Module | Description |
|---|---|
ffi |
Raw FFI bindings + struct definitions (VM, List, Item, String) |
api |
Ring VM API wrappers (58 functions) |
list |
List manipulation (66 functions) |
string |
String operations (15 functions) |
state |
State management (31 functions) |
vm |
VM control and execution (44 functions) |
item |
Item/value operations (23 functions) |
general |
File/directory utilities (14 functions) |
macros |
Ergonomic helper macros |
API Coverage
188 / 386 functions (48%) of Ring's public C API.
| Header | Coverage |
|---|---|
vm.h |
29/29 (100%) |
ringapi.h |
41/41 (100%) |
state.h |
16/20 (80%) |
rstring.h |
11/22 (50%) |
ritem.h |
17/34 (50%) |
general.h |
12/28 (43%) |
rlist.h |
54/131 (41%) |
vmgc.h |
7/81 (9%) |
We focused on functions useful for writing extensions. rlist.h and vmgc.h have _gc variants we skip.
Embedding Ring
To embed Ring in a Rust application:
Cargo.toml:
[]
= "0.1"
Running Code
use *;
Sharing Variables
use *;
API Reference
| Function | Requires | Description |
|---|---|---|
ring_state_init() |
- | Create state with initialized VM |
ring_state_new() |
- | Create state for compilation |
ring_state_runcode_str() |
ring_state_init() |
Execute code on initialized VM |
ring_state_runfile_str() |
ring_state_new() |
Compile and run a file |
ring_state_runstring_str() |
ring_state_new() |
Compile and run a string |
ring_state_findvar_str() |
ring_state_init() |
Find a variable by name |
ring_state_delete() |
- | Clean up and free the state |
See examples/embed/ for a complete working example.
License
This project is licensed under the MIT License - see the LICENSE file for details.