ocaml-interop

build crate documentation license

Zinc-iron alloy coating is used in parts that need very good corrosion protection.

ocaml-interop is an OCaml<->Rust FFI with an emphasis on safety inspired by caml-oxide and ocaml-rs.

Read the full documentation here.

Report issues on Github.

Table of Contents

How does it work

ocaml-interop, just like caml-oxide, encodes the invariants of OCaml's garbage collector into the rules of Rust's borrow checker. Any violation of these invariants results in a compilation error produced by Rust's borrow checker.

This requires that the user is explicit about delimiting blocks that interact with the OCaml runtime, and that calls into the OCaml runtime are done only inside these blocks, and wrapped by a few special macros.

A quick taste

Convert between plain OCaml and Rust values

rust let rust_string = ocaml_string.to_rust(); let new_ocaml_string = to_ocaml!(gc, rust_string);

Convert between Rust and OCaml structs/records

ocaml (* OCaml *) type my_record = { string_field: string; tuple_field: (string * int); }

```rust // Rust struct MyStruct { stringfield: String, tuplefield: (String, i64), }

implconvocamlrecord! { MyStruct { stringfield: String, tuple_field: (String, i64), } }

// ...

let ruststruct = ocamlrecord.torust(); let newocamlrecord = toocaml!(gc, rust_struct); ```

Convert between OCaml and Rust variants/enums

ocaml (* OCaml *) type my_variant = | EmptyTag | TagWithInt of int

```rust // Rust enum MyEnum { EmptyTag, TagWithInt(i64), }

implconvocaml_variant! { MyEnum { EmptyTag, TagWithInt(OCamlInt), } }

// ...

let rustenum = ocamlvariant.torust(); let newocamlvariant = toocaml!(gc, rust_enum); ```

Call OCaml functions from Rust

ocaml (* OCaml *) Callback.register "ocaml_print_endline" print_endline

```rust ocaml! { fn ocamlprintendline(s: String); }

// ...

let ocamlstring = toocaml!(gc, "hello OCaml!"); ocamlcall!(ocamlprintendline(gc, ocamlstring)).unwrap(); ```

Call Rust functions from OCaml

rust // Rust ocaml_export! { pub fn twice_boxed_int(gc, num: OCaml<OCamlInt64>) -> OCaml<OCamlInt64> { let num = num.to_rust(); let result = num * 2; ocaml_alloc!(result.to_ocaml(gc)) } }

```ocaml (* OCaml *) external rusttwiceboxedint: int64 -> int64 = "twiceboxed_int"

(* ... *)

let result = rusttwiceboxed_int 123L in (* ... *) ```

References and links