Skip to main content

alien_ffi/
lib.rs

1
2extern crate typed_arena;
3
4pub mod caml_ffi_types;
5pub mod caml_opaque;
6
7mod caml_values;
8mod caml_ba;
9
10pub use caml_ffi_types::*;
11pub use caml_opaque::*;
12pub use caml_values::*;
13
14use typed_arena::Arena;
15use caml_ba::Bigarray;
16
17//----------------------------------------------------------------------
18// C Functions
19//----------------------------------------------------------------------
20
21extern {
22    pub fn caml_ba_alloc_u8(data: *const Cvoid, ndims: Cint, dims: *const Clong) -> Value;
23
24    // Custom
25    pub fn set_finalize(ops: *const CustomOperations, f: extern fn (Value));
26}
27
28//----------------------------------------------------------------------
29// Retrieve a pointer to CustomOperations (syntactic sugar)
30//----------------------------------------------------------------------
31
32pub fn ops(ops: &'static CustomOperations) -> *const CustomOperations {
33    ops as *const CustomOperations
34}
35
36//----------------------------------------------------------------------
37
38pub fn caml_finalize(ops: &'static CustomOperations, f: extern fn (Value)) {
39    unsafe { set_finalize(ops as *const CustomOperations, f) }
40}
41
42//----------------------------------------------------------------------
43// Rust interface
44
45pub fn caml_ba_data(value: Value) -> *mut Cvoid {
46    assert!(tag_of_value(value) == CUSTOM_TAG);
47    unsafe {
48	let ba_offset = (value as *mut Value).offset(1 as isize);
49	let ba = ba_offset as *const Bigarray;
50	(*ba).data as *mut Cvoid
51    }
52}
53
54pub fn caml_to_slice<T>(value: Value) -> &'static [T] {
55    assert!(tag_of_value(value) == CUSTOM_TAG);
56    unsafe {
57	let ba_offset = (value as *mut Value).offset(1 as isize);
58	let ba = ba_offset as *const Bigarray;
59	let len = (*ba).dim as usize;
60	std::slice::from_raw_parts((*ba).data as *const T, len)
61    }
62}
63
64// Generic external bigarray allocation
65
66pub fn acquire_external<T>(ba: Value) -> &'static T {
67    let data_ptr = caml_ba_data(ba) as *mut T;
68    unsafe { data_ptr.as_ref().unwrap() }
69}
70
71pub fn alloc_external<T>(ext: T) -> Value {
72    let ext_box = Box::new(ext);
73    let ext_ptr = Box::into_raw(ext_box);
74    let size = std::mem::size_of::<T>();
75    let dims = &[size as Clong];
76    unsafe { caml_ba_alloc_u8(ext_ptr as *const Cvoid, 1, dims.as_ptr()) }
77}
78
79pub fn free_external<T>(ba: Value) -> () {
80    let data_ptr = caml_ba_data(ba) as *mut T;
81    drop(unsafe { Box::from_raw(data_ptr) })
82}
83
84// Arena allocation
85
86pub fn acquire_ba_arena(arena: Value) -> &'static Arena<Vec<u8>> {
87    acquire_external::<Arena<Vec<u8>>>(arena)
88}
89
90pub fn arena_alloc_ba(arena: &'static Arena<Vec<u8>>, msg: Vec<u8>) -> Value {
91    let size = std::mem::size_of::<u8>() * msg.len();
92    let dims = &[size as Clong];
93    let mem = arena.alloc(msg);
94    unsafe { caml_ba_alloc_u8(mem.as_ptr() as *const Cvoid, 1, dims.as_ptr()) }
95}
96
97//----------------------------------------------------------------------
98// OCaml interface
99
100#[no_mangle]
101pub extern fn arena_alloc(_unit: Value) -> Value {
102    alloc_external::<Arena<Vec<u8>>>(Arena::new())
103}
104
105#[no_mangle]
106pub extern fn arena_free(arena: Value) -> Value {
107    free_external::<Arena<Vec<u8>>>(arena);
108    caml_unit()
109}
110