macro_rules! custom {
($name:ident $(<$($t:tt),*>)? $({$($k:ident : $v:expr),* $(,)? })?) => { ... };
{name : $name:expr $(, fixed_length: $fl:expr)? $(, $($k:ident : $v:expr),*)? $(,)? } => { ... };
}
Expand description
Create a custom OCaml type from an existing Rust type
See the struct custom_operations section in the OCaml manual for more information about each field
struct MyType {
s: String,
i: i32,
}
unsafe extern "C" fn mytype_compare(a: ocaml::Raw, b: ocaml::Raw) -> i32 {
let a = a.as_pointer::<MyType>();
let b = b.as_pointer::<MyType>();
let a_i = a.as_ref().i;
let b_i = b.as_ref().i;
if a_i == b_i {
return 0
}
if a_i < b_i {
return -1;
}
1
}
ocaml::custom!(MyType {
compare: mytype_compare,
});
// This is equivalent to
struct MyType2 {
s: String,
i: i32,
}
// This is the default finalizer
unsafe extern "C" fn mytype2_finalizer(v: ocaml::Raw) {
let ptr = v.as_pointer::<MyType2>();
ptr.drop_in_place();
}
impl ocaml::Custom for MyType2 {
const NAME: &'static str = "rust.MyType\0";
const OPS: ocaml::custom::CustomOps = ocaml::custom::CustomOps {
identifier: Self::NAME.as_ptr() as *mut ocaml::sys::Char,
finalize: Some(mytype2_finalizer),
compare: Some(mytype_compare),
.. ocaml::custom::DEFAULT_CUSTOM_OPS
};
}
Additionally, custom
can be used inside the impl
block:
extern "C" fn implexample_finalizer(_: ocaml::Raw) {
println!("This runs when the value gets garbage collected");
}
struct ImplExample<'a>(&'a str);
impl<'a> ocaml::Custom for ImplExample<'a> {
ocaml::custom! {
name: "rust.ImplExample",
finalize: implexample_finalizer
}
}
// This is equivalent to:
struct ImplExample2<'a>(&'a str);
ocaml::custom!(ImplExample2<'a> {
finalize: implexample_finalizer,
});