1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use crate::error::OCamlException;
use crate::mlvalues::tag;
use crate::mlvalues::{extract_exception, is_exception_result, tag_val, RawOCaml};
use crate::value::OCaml;
use crate::{OCamlRef, OCamlRuntime};
use ocaml_sys::{
caml_callback2_exn, caml_callback3_exn, caml_callbackN_exn, caml_callback_exn, caml_named_value,
};
#[derive(Copy, Clone)]
pub struct OCamlClosure(*const RawOCaml);
unsafe impl Sync for OCamlClosure {}
impl OCamlClosure {
pub fn named(name: &str) -> Option<OCamlClosure> {
let named = unsafe {
let s = match std::ffi::CString::new(name) {
Ok(s) => s,
Err(_) => return None,
};
caml_named_value(s.as_ptr())
};
if named.is_null() || unsafe { tag_val(*named) } != tag::CLOSURE {
None
} else {
Some(OCamlClosure(named))
}
}
pub fn call<'a, T, R>(&self, cr: &'a mut OCamlRuntime, arg: OCamlRef<T>) -> OCaml<'a, R> {
let result = unsafe { caml_callback_exn(*self.0, arg.get_raw()) };
self.handle_call_result(cr, result)
}
pub fn call2<'a, T, U, R>(
&self,
cr: &'a mut OCamlRuntime,
arg1: OCamlRef<T>,
arg2: OCamlRef<U>,
) -> OCaml<'a, R> {
let result = unsafe { caml_callback2_exn(*self.0, arg1.get_raw(), arg2.get_raw()) };
self.handle_call_result(cr, result)
}
pub fn call3<'a, T, U, V, R>(
&self,
cr: &'a mut OCamlRuntime,
arg1: OCamlRef<T>,
arg2: OCamlRef<U>,
arg3: OCamlRef<V>,
) -> OCaml<'a, R> {
let result =
unsafe { caml_callback3_exn(*self.0, arg1.get_raw(), arg2.get_raw(), arg3.get_raw()) };
self.handle_call_result(cr, result)
}
pub fn call_n<'a, R>(&self, cr: &'a mut OCamlRuntime, args: &mut [RawOCaml]) -> OCaml<'a, R> {
let len = args.len();
let result = unsafe { caml_callbackN_exn(*self.0, len, args.as_mut_ptr()) };
self.handle_call_result(cr, result)
}
#[inline]
fn handle_call_result<'a, R>(
&self,
cr: &'a mut OCamlRuntime,
result: RawOCaml,
) -> OCaml<'a, R> {
if is_exception_result(result) {
let ex = unsafe { OCamlException::of(extract_exception(result)) };
panic!("OCaml exception, message: {:?}", ex.message())
} else {
unsafe { OCaml::new(cr, result) }
}
}
}
pub type OCamlFn1<'a, A, Ret> = unsafe fn(&'a mut OCamlRuntime, OCamlRef<A>) -> OCaml<'a, Ret>;
pub type OCamlFn2<'a, A, B, Ret> =
unsafe fn(&'a mut OCamlRuntime, OCamlRef<A>, OCamlRef<B>) -> OCaml<'a, Ret>;
pub type OCamlFn3<'a, A, B, C, Ret> =
unsafe fn(&'a mut OCamlRuntime, OCamlRef<A>, OCamlRef<B>, OCamlRef<C>) -> OCaml<'a, Ret>;
pub type OCamlFn4<'a, A, B, C, D, Ret> = unsafe fn(
&'a mut OCamlRuntime,
OCamlRef<A>,
OCamlRef<B>,
OCamlRef<C>,
OCamlRef<D>,
) -> OCaml<'a, Ret>;
pub type OCamlFn5<'a, A, B, C, D, E, Ret> = unsafe fn(
&'a mut OCamlRuntime,
OCamlRef<A>,
OCamlRef<B>,
OCamlRef<C>,
OCamlRef<D>,
OCamlRef<E>,
) -> OCaml<'a, Ret>;