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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
// Copyright (c) Viable Systems and TezEdge Contributors
// SPDX-License-Identifier: MIT
//! _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**
//!
//! **IMPORTANT: Starting with version `0.11.0` only OCaml 5.x is supported**
//!
//! [ocaml-interop](https://github.com/tizoc/ocaml-interop) is an OCaml<->Rust FFI with an emphasis
//! on safety inspired by [caml-oxide](https://github.com/stedolan/caml-oxide),
//! [ocaml-rs](https://github.com/zshipko/ocaml-rs) and [CAMLroot](https://arxiv.org/abs/1812.04905).
//!
//! ## Table of Contents
//!
//! - [Usage](#usage)
//! * [Runtime Initialization and Management](#runtime-initialization-and-management)
//! * [Acquiring and Using the OCaml Runtime Handle](#acquiring-and-using-the-ocaml-runtime-handle)
//! * [OCaml value representation](#ocaml-value-representation)
//! * [Converting between OCaml and Rust data](#converting-between-ocaml-and-rust-data)
//! * [Calling convention](#calling-convention)
//! * [OCaml exceptions](#ocaml-exceptions)
//! * [Calling into OCaml from Rust](#calling-into-ocaml-from-rust)
//! * [Calling into Rust from OCaml](#calling-into-rust-from-ocaml)
//! - [User Guides](user_guides)
//! - [References and links](#references-and-links)
//!
//! ## Usage
//!
//! This section provides a high-level overview of `ocaml-interop`. For detailed explanations,
//! tutorials, and best practices, please refer to the [User Guides module](user_guides).
//!
//! ### Runtime Initialization and Management
//!
//! Proper initialization and management of the OCaml runtime is crucial, especially when Rust
//! code drives the execution. This involves using [`OCamlRuntime::init`] and managing its
//! lifecycle with [`OCamlRuntimeStartupGuard`].
//!
//! For detailed information, see
//! [OCaml Runtime (Part 5)](user_guides::part5_managing_the_ocaml_runtime_for_rust_driven_programs).
//!
//! ### Acquiring and Using the OCaml Runtime Handle
//!
//! Most interop operations require an OCaml runtime handle (`cr: &mut OCamlRuntime`).
//! This handle is obtained differently depending on whether Rust calls OCaml or OCaml calls Rust.
//!
//! See these guides for more details:
//! - [Part 2: Fundamental Concepts](user_guides::part2_fundamental_concepts)
//! - [OCaml Runtime (Part 5)](user_guides::part5_managing_the_ocaml_runtime_for_rust_driven_programs)
//!
//! ### OCaml value representation
//!
//! OCaml values are represented in Rust using types like [`OCaml<'gc, T>`](OCaml),
//! [`BoxRoot<T>`](BoxRoot), and [`OCamlRef<'a, T>`](OCamlRef), each with specific roles
//! in memory management and GC interaction.
//!
//! Learn more in [Part 2: Fundamental Concepts](user_guides::part2_fundamental_concepts).
//!
//! ### Converting between OCaml and Rust data
//!
//! The traits [`FromOCaml`] and [`ToOCaml`] facilitate data conversion
//! between Rust and OCaml types.
//!
//! For conversion details and examples, refer to
//! [Part 2: Fundamental Concepts](user_guides::part2_fundamental_concepts), as well as the guides
//! on exporting and invoking functions.
//!
//! ### Calling convention
//!
//! `ocaml-interop` uses a caller-rooted argument convention for safety, where the caller is
//! responsible for ensuring arguments are rooted before a function call.
//!
//! This is explained further in [Part 2: Fundamental Concepts](user_guides::part2_fundamental_concepts).
//!
//! ### OCaml exceptions
//!
//! By default, Rust panics in exported functions are caught and translated to OCaml exceptions.
//! Conversely, OCaml exceptions raised during calls from Rust will result in Rust panics.
//!
//! For error handling strategies, see
//! [Part 2: Fundamental Concepts](user_guides::part2_fundamental_concepts) and
//! [Part 6: Advanced Topics](user_guides::part6_advanced_topics).
//!
//! ### Calling into OCaml from Rust
//!
//! To call OCaml functions from Rust, they typically need to be registered in OCaml
//! (e.g., using `Callback.register`) and then declared in Rust using the [`ocaml!`] macro.
//! This setup allows Rust to find and invoke these OCaml functions.
//!
//! For a comprehensive guide on calling OCaml functions from Rust,
//! including detailed examples and best practices, please see:
//! [Invoking OCaml Functions (Part 4)](user_guides::part4_invoking_ocaml_functions_from_rust).
//!
//! ### Calling into Rust from OCaml
//!
//! Rust functions can be exposed to OCaml using the [`#[ocaml_interop::export]`](export)
//! procedural macro, which handles FFI boilerplate, type marshalling, and panic safety.
//!
//! Attributes like `no_panic_catch`, `bytecode`, and `noalloc` allow customization.
//!
//! For a detailed guide, see
//! [Exporting Rust Functions (Part 3)](user_guides::part3_exporting_rust_functions_to_ocaml).
//!
//! ## References and links
//!
//! - OCaml Manual: [Chapter 20 Interfacing C with OCaml](https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html).
//! - [Safely Mixing OCaml and Rust](https://docs.google.com/viewer?a=v&pid=sites&srcid=ZGVmYXVsdGRvbWFpbnxtbHdvcmtzaG9wcGV8Z3g6NDNmNDlmNTcxMDk1YTRmNg) paper by Stephen Dolan.
//! - [Safely Mixing OCaml and Rust](https://www.youtube.com/watch?v=UXfcENNM_ts) talk by Stephen Dolan.
//! - [CAMLroot: revisiting the OCaml FFI](https://arxiv.org/abs/1812.04905).
//! - [caml-oxide](https://github.com/stedolan/caml-oxide), the code from that paper.
//! - [ocaml-rs](https://github.com/zshipko/ocaml-rs), another OCaml<->Rust FFI library.
pub use crateBoxRoot;
pub use crate;
pub use crate;
pub use cratealloc_cons as cons;
pub use crateOCamlRef;
pub use crate;
pub use crate;
pub use crate;
pub use crateOCaml;
/// Exports a Rust function to OCaml.
///
/// This procedural macro handles the complexities of the OCaml Foreign Function Interface (FFI),
/// allowing Rust functions to be called from OCaml code. It generates the necessary
/// `extern "C"` wrapper function and manages type conversions and memory safety.
///
/// ## Basic Usage
///
/// ```rust
/// use ocaml_interop::{OCaml, OCamlRuntime, OCamlBytes, OCamlInt, ToOCaml};
///
/// #[ocaml_interop::export]
/// fn process_bytes(cr: &mut OCamlRuntime, data: OCaml<OCamlBytes>) -> OCaml<OCamlInt> {
/// let byte_slice: &[u8] = &data.to_rust::<Vec<u8>>();
/// let length = byte_slice.len() as i64;
/// length.to_ocaml(cr)
/// }
/// ```
///
/// The macro generates an `extern "C"` function with the same identifier as the Rust function
/// (e.g., `process_bytes` in the example above).
///
/// ## Key Features
///
/// * **Automatic FFI Boilerplate:** Generates the `extern "C"` wrapper and handles argument/return
/// value marshalling.
/// * **Type Safety:** Utilizes types like [`OCaml<T>`] and [`BoxRoot<T>`] to provide safe
/// abstractions over OCaml values.
/// * **Argument Handling:**
/// * The first argument *must* be [`&mut OCamlRuntime`] (or [`&OCamlRuntime`] if `noalloc`
/// is used).
/// * [`OCaml<'gc, T>`]: For OCaml values passed as arguments. These are *not* automatically
/// rooted by the macro. Their lifetime `'gc` is tied to the current function call's
/// [`OCamlRuntime`] scope. Root them explicitly (e.g., with [`BoxRoot<T>`]) if they need to
/// persist beyond this scope or be re-passed to OCaml.
/// * [`BoxRoot<T>`]: If an argument is declared as `BoxRoot<T>`, the macro automatically
/// roots the incoming OCaml value before your function body executes. This ensures the value
/// is valid throughout the function, even across further OCaml calls.
/// * **Direct Primitive Types:** Supports direct mapping for Rust primitive types like `f64`,
/// `i64`, `i32`, `bool`, and `isize` as arguments. The OCaml `external` declaration
/// must use corresponding `[@@unboxed]` or `[@untagged]` attributes.
/// * **Return Types:**
/// * Typically, functions return [`OCaml<T>`].
/// * Direct primitive types (see above) can also be returned.
/// * **Panic Handling:**
/// * By default, Rust panics are caught and raised as an OCaml exception (`RustPanic of string`
/// if registered, otherwise `Failure`).
/// * This can be disabled with `#[ocaml_interop::export(no_panic_catch)]`. Use with caution.
/// * **Bytecode Function Generation:**
/// * Use `#[ocaml_interop::export(bytecode = "my_ocaml_bytecode_function_name")]` to generate
/// a wrapper for OCaml bytecode compilation.
/// * The OCaml `external` declaration should then specify both the bytecode and native
/// function names: `external rust_fn : int -> int = "bytecode_stub_name" "native_c_stub_name"`.
/// * **`noalloc` Attribute:**
/// * `#[ocaml_interop::export(noalloc)]` for functions that must not trigger OCaml GC
/// allocations.
/// * Requires the runtime argument to be `cr: &OCamlRuntime` (immutable).
/// * Implies `no_panic_catch`. Panics in `noalloc` functions lead to undefined behavior.
/// * The corresponding OCaml `external` **must** be annotated with `[@@noalloc]`.
/// * The user is responsible for ensuring no OCaml allocations occur in the Rust function body.
///
/// ## Argument and Return Value Conventions
///
/// The macro handles the conversion between OCaml's representation and Rust types.
///
/// ### OCaml Values
///
/// * [`OCaml<T>`]: Represents an OCaml value that is not yet rooted. Its lifetime is tied to the
/// current OCaml runtime scope.
/// * [`BoxRoot<T>`]: Represents an OCaml value that has been rooted and is protected from the OCaml
/// garbage collector. The `#[ocaml_interop::export]` macro can automatically root arguments
/// if they are specified as `BoxRoot<T>`.
///
/// ### Direct Primitive Type Mapping
///
/// For performance, certain Rust primitive types can be directly mapped to unboxed or untagged
/// OCaml types. This avoids boxing overhead.
///
/// | Rust Type | OCaml Type | OCaml `external` Attribute(s) Needed |
/// | :-------- | :---------------- | :----------------------------------- |
/// | `f64` | `float` | `[@@unboxed]` (or on arg/ret type) |
/// | `i64` | `int64` | `[@@unboxed]` (or on arg/ret type) |
/// | `i32` | `int32` | `[@@unboxed]` (or on arg/ret type) |
/// | `bool` | `bool` | `[@untagged]` (or on arg/ret type) |
/// | `isize` | `int` | `[@untagged]` (or on arg/ret type) |
/// | `()` | `unit` | (Usually implicit for return) |
///
/// **Example (OCaml `external` for direct primitives):**
/// ```ocaml
/// external process_primitive_values :
/// (int [@untagged]) ->
/// (bool [@untagged]) ->
/// (float [@unboxed]) ->
/// (int32 [@unboxed]) =
/// "" "process_primitive_values"
/// ```
///
/// For more detailed information, refer to the user guides, particularly
/// [Exporting Rust Functions (Part 3)](user_guides::part3_exporting_rust_functions_to_ocaml)
///
/// [`OCaml<T>`]: OCaml
/// [`OCaml<'gc, T>`]: OCaml
/// [`BoxRoot<T>`]: BoxRoot
/// [`&mut OCamlRuntime`]: OCamlRuntime
/// [`&OCamlRuntime`]: OCamlRuntime
pub use export;