#ocaml #ffi #interop #rust

ocaml-interop

Utilities for Rust and OCaml interoperability

28 releases (6 breaking)

0.8.7 Oct 12, 2021
0.8.5 Aug 16, 2021
0.8.4 May 18, 2021
0.7.2 Mar 18, 2021
0.4.4 Nov 3, 2020

#308 in Command line utilities

Download history 2220/week @ 2021-07-06 2592/week @ 2021-07-13 2496/week @ 2021-07-20 3254/week @ 2021-07-27 3602/week @ 2021-08-03 3679/week @ 2021-08-10 3788/week @ 2021-08-17 4332/week @ 2021-08-24 3794/week @ 2021-08-31 2669/week @ 2021-09-07 3444/week @ 2021-09-14 2004/week @ 2021-09-21 2651/week @ 2021-09-28 2918/week @ 2021-10-05 2828/week @ 2021-10-12 3108/week @ 2021-10-19

13,497 downloads per month
Used in ocaml

MIT license

125KB
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
(* ... *)

References and links

Dependencies

~130–270KB