Expand description
ocaml-rs is a library for directly interacting with the C OCaml runtime, in Rust.
The OCaml manual chapter Interfacing C with OCaml does a great job of explaining low-level details about how to safely interact with the OCaml runtime. This crate aims to be a slightly higher-level of abstraction, with minimal added overhead.
§Getting started
Take a look at the ocaml-rust-starter project for a basic example to help get started with ocaml-rs
.
§Examples
use ocaml::FromValue;
// Automatically derive `ToValue` and `FromValue`
#[cfg(feature = "derive")]
#[derive(ocaml::ToValue, ocaml::FromValue)]
#[ocaml::sig("{name: string; i: int}")]
struct Example {
name: String,
i: ocaml::Int,
}
#[cfg(feature = "derive")]
#[ocaml::func]
#[ocaml::sig("example -> example")]
pub fn incr_example(mut e: Example) -> Example {
e.i += 1;
e
}
#[cfg(feature = "derive")]
#[ocaml::func]
#[ocaml::sig("int -> int * int * int")]
pub fn build_tuple(i: ocaml::Int) -> (ocaml::Int, ocaml::Int, ocaml::Int) {
(i + 1, i + 2, i + 3)
}
/// A name for the garbage collector handle can also be specified:
#[cfg(feature = "derive")]
#[ocaml::func(my_gc_handle)]
#[ocaml::sig("unit -> string")]
pub unsafe fn my_string() -> ocaml::Value {
ocaml::Value::string("My string")
}
#[cfg(feature = "derive")]
#[ocaml::func]
#[ocaml::sig("float array -> float")]
pub fn average(arr: ocaml::Array<f64>) -> Result<f64, ocaml::Error> {
let mut sum = 0f64;
for i in 0..arr.len() {
sum += arr.get_f64(i)?;
}
Ok(sum / arr.len() as f64)
}
// A `native_func` must take `ocaml::Value` for every argument or `f64` for
// every unboxed argument and return an `ocaml::Value` (or `f64`).
// `native_func` has minimal overhead compared to wrapping with `func`
#[cfg(feature = "derive")]
#[ocaml::native_func]
#[ocaml::sig("int -> int")]
pub unsafe fn incr(value: ocaml::Value) -> ocaml::Value {
let i = isize::from_value(value);
ocaml::Value::int(i + 1)
}
// This is equivalent to:
#[no_mangle]
pub unsafe extern "C" fn incr2(value: ocaml::Value) -> ocaml::Value {
ocaml::body!(gc: {
let i = isize::from_value(value);
ocaml::Value::int( i + 1)
})
}
// `ocaml::native_func` is responsible for:
// - Ensures that #[no_mangle] and extern "C" are added, in addition to wrapping
// - Wraps the function body using `ocaml::body!`
// Finally, if your function is marked [@@unboxed] and [@@noalloc] in OCaml then you can avoid
// boxing altogether for f64 arguments using a plain C function and a bytecode function
// definition:
#[no_mangle]
pub extern "C" fn incrf(input: f64) -> f64 {
input + 1.0
}
#[cfg(feature = "derive")]
#[ocaml::bytecode_func]
pub fn incrf_bytecode(input: f64) -> f64 {
incrf(input)
}
The OCaml stubs would look like this:
type example = {
name: string;
i: int;
}
external incr_example: example -> example = "incr_example"
external build_tuple: int -> int * int * int = "build_tuple"
external average: float array -> float = "average"
external incr: int -> int = "incr"
external incr2: int -> int = "incr2"
external incrf: float -> float = "incrf_bytecode" "incrf" [@@unboxed] [@@noalloc]
Excluding the incrf
example, these can also be automatically generated using ocaml-build
For more information see the ocaml-rs book
Re-exports§
pub use crate::custom::Custom;
pub use crate::runtime::Runtime;
pub use crate::macros::initial_setup;
pub use ocaml_sys as sys;
pub use crate::runtime::*;
Modules§
bigarray
contains wrappers for OCamlBigarray
values. These types can be used to transfer arrays of numbers between Rust and OCaml directly without the allocation overhead of anarray
orlist
- Custom types, used for allocating Rust values owned by the OCaml garbage collector
- Rooted values
- Functions for interacting with the OCaml runtime
Macros§
- Convenience macro to create an OCaml array
body!
is needed to help the OCaml runtime to manage garbage collection, it should be used to wrap the body of each function exported to OCaml. Panics from Rust code will automatically be unwound/caught here (unless theno-std
feature is enabled)- Create a custom OCaml type from an existing Rust type
- Derives
Custom
with the given finalizer for a type - Convert OCaml value into a callable closure
- Import OCaml functions
- Convenience macro to create an OCaml list
Structs§
Array<A>
wraps an OCaml'a array
without converting it to RustList<A>
wraps an OCaml'a list
without converting it to Rust, this introduces no additional overhead compared to aValue
type- A handle to a Rust value/reference owned by the OCaml heap.
- Wrapper around sys::Value
- OCaml tags are used to provide type information to the garbage collector
Enums§
- Errors that are translated directly into OCaml exceptions
- Error returned by
ocaml-rs
functions - Value wraps the native OCaml
value
type
Traits§
FromValue
is used to convert from OCaml values to Rust typesToValue
is used to convert from Rust types to OCaml values
Type Aliases§
- OCaml
float
- Integer type that converts to OCaml
int
- Unsigned integer type that converts to OCaml
int
Attribute Macros§
bytecode_func
is used export Rust functions to OCaml, performing the necessary wrapping/unwrapping automatically.func
is used export Rust functions to OCaml, performing the necessary wrapping/unwrapping automatically.native_func
is used export Rust functions to OCaml, it has much lower overhead thanfunc
and expects all arguments and return type to to beValue
.
Derive Macros§
- Derive
ocaml::FromValue
- Derive
ocaml::ToValue