#ocaml #interop #ffi #rust

ocaml-interop

Utilities for Rust and OCaml interoperability

33 releases

0.10.0 Jan 28, 2024
0.9.2 Aug 27, 2023
0.9.1 Jul 12, 2023
0.8.8 Mar 23, 2022
0.4.4 Nov 3, 2020

#1 in #ocaml

Download history 5019/week @ 2024-01-24 5749/week @ 2024-01-31 2442/week @ 2024-02-07 3896/week @ 2024-02-14 3246/week @ 2024-02-21 2988/week @ 2024-02-28 3393/week @ 2024-03-06 2709/week @ 2024-03-13 3044/week @ 2024-03-20 3898/week @ 2024-03-27 3950/week @ 2024-04-03 4758/week @ 2024-04-10 5151/week @ 2024-04-17 6123/week @ 2024-04-24 7392/week @ 2024-05-01 7452/week @ 2024-05-08

26,873 downloads per month
Used in 3 crates (via ocaml)

MIT license

135KB
2.5K SLoC

ocaml-interop

build crate documentation license

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

API IS CONSIDERED UNSTABLE AT THE MOMENT AND IS LIKELY TO CHANGE IN THE FUTURE

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

Read the full documentation here.

Report issues on Github.

A quick taste

Convert between plain OCaml and Rust values

let rust_string = ocaml_string.to_rust();
// `cr` = OCaml runtime handle
let new_ocaml_string = rust_string.to_ocaml(cr);

Convert between Rust and OCaml structs/records

(* OCaml *)
type my_record = {
  string_field: string;
  tuple_field: (string * int);
}
// Rust
struct MyStruct {
    string_field: String,
    tuple_field: (String, i64),
}

impl_conv_ocaml_record! {
    MyStruct {
        string_field: String,
        tuple_field: (String, i64),
    }
}

// ...

let rust_struct = ocaml_record.to_rust();
let new_ocaml_record = rust_struct.to_ocaml(cr);

Convert between OCaml and Rust variants/enums

(* OCaml *)
type my_variant =
  | EmptyTag
  | TagWithInt of int
// Rust
enum MyEnum {
    EmptyTag,
    TagWithInt(i64),
}

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

// ...

let rust_enum = ocaml_variant.to_rust();
let new_ocaml_variant = rust_enum.to_ocaml(cr);

Call OCaml functions from Rust

(* OCaml *)
Callback.register "ocaml_print_endline" print_endline
// Rust
ocaml! {
    fn ocaml_print_endline(s: String);
}

// ...

let ocaml_string = "hello OCaml!".to_boxroot(cr);
ocaml_print_endline(cr, &ocaml_string);

Call Rust functions from OCaml

// Rust
ocaml_export! {
    pub fn twice_boxed_int(cr, num: OCamlRef<OCamlInt64>) -> OCaml<OCamlInt64> {
        let num = num.to_rust(cr);
        let result = num * 2;
        result.to_ocaml(cr)
    }
}
(* OCaml *)
external rust_twice_boxed_int: int64 -> int64 = "twice_boxed_int"

(* ... *)

let result = rust_twice_boxed_int 123L in
(* ... *)

Dependencies

~145–320KB