1//! Middle layer providing a somewhat safer (but still quite unsafe)
2//! API.
3//!
4//! The main idea of the middle layer is to wrap types [`low::ffi_cif`]
5//! and [`low::ffi_closure`] as [`Cif`] and [`Closure`], respectively,
6//! so that their resources are managed properly. However, calling a
7//! function via a CIF or closure is still unsafe because argument types
8//! aren’t checked. See the [`high`](crate::high) layer for closures
9//! with type-checked arguments.
10
11use std::any::Any;
12use std::marker::PhantomData;
13use std::os::raw::c_void;
14
15use crate::low;
16pub use crate::low::{ffi_abi as FfiAbi, ffi_abi_FFI_DEFAULT_ABI, Callback, CallbackMut, CodePtr};
17
18mod util;
19
20mod types;
21pub use types::Type;
22
23mod builder;
24pub use builder::Builder;
25
26/// Contains an untyped pointer to a function argument.
27///
28/// When calling a function via a [CIF](Cif), each argument
29/// must be passed as a C `void*`. Wrapping the argument in the [`Arg`]
30/// struct accomplishes the necessary coercion.
31#[derive(Clone, Debug)]
32#[repr(C)]
33pub struct Arg(*mut c_void);
34
35impl Arg {
36 /// Coerces an argument reference into the [`Arg`] type.
37 ///
38 /// This is used to wrap each argument pointer before passing them
39 /// to [`Cif::call`].
40 pub fn new<T>(r: &T) -> Self {
41 Arg(r as *const T as *mut c_void)
42 }
43}
44
45/// Coerces an argument reference into the [`Arg`] type.
46///
47/// This is used to wrap each argument pointer before passing them
48/// to [`Cif::call`]. (This is the same as [`Arg::new`]).
49pub fn arg<T>(r: &T) -> Arg {
50 Arg::new(r)
51}
52
53/// Describes the calling convention and types for calling a function.
54///
55/// This is the middle layer’s wrapping of the [`low`](crate::low) and
56/// [`raw`](crate::raw) layers’ [`low::ffi_cif`]. An initialized CIF
57/// contains references to an array of argument types and a result type,
58/// each of which may be allocated on the heap. `Cif` manages the memory
59/// of those referenced objects.
60///
61/// Construct with [`Cif::new`].
62///
63/// # Examples
64///
65/// ```
66/// extern "C" fn add(x: f64, y: &f64) -> f64 {
67/// return x + y;
68/// }
69///
70/// use libffi::middle::*;
71///
72/// let args = vec![Type::f64(), Type::pointer()];
73/// let cif = Cif::new(args.into_iter(), Type::f64());
74///
75/// let n = unsafe { cif.call(CodePtr(add as *mut _), &[arg(&5f64), arg(&&6f64)]) };
76/// assert_eq!(11f64, n);
77/// ```
78#[derive(Debug)]
79pub struct Cif {
80 cif: low::ffi_cif,
81 args: types::TypeArray,
82 result: Type,
83}
84
85// To clone a Cif we need to clone the types and then make sure the new
86// ffi_cif refers to the clones of the types.
87impl Clone for Cif {
88 fn clone(&self) -> Self {
89 let mut copy: Cif = Cif {
90 cif: self.cif,
91 args: self.args.clone(),
92 result: self.result.clone(),
93 };
94
95 copy.cif.arg_types = copy.args.as_raw_ptr();
96 copy.cif.rtype = copy.result.as_raw_ptr();
97
98 copy
99 }
100}
101
102impl Cif {
103 /// Creates a new [CIF](Cif) for the given argument and result
104 /// types.
105 ///
106 /// Takes ownership of the argument and result [`Type`]s, because
107 /// the resulting [`Cif`] retains references to them. Defaults to
108 /// the platform’s default calling convention; this can be adjusted
109 /// using [`Cif::set_abi`].
110 pub fn new<I>(args: I, result: Type) -> Self
111 where
112 I: IntoIterator<Item = Type>,
113 I::IntoIter: ExactSizeIterator<Item = Type>,
114 {
115 let args = args.into_iter();
116 let nargs = args.len();
117 let args = types::TypeArray::new(args);
118 let mut cif: low::ffi_cif = Default::default();
119
120 unsafe {
121 low::prep_cif(
122 &mut cif,
123 low::ffi_abi_FFI_DEFAULT_ABI,
124 nargs,
125 result.as_raw_ptr(),
126 args.as_raw_ptr(),
127 )
128 }
129 .expect("low::prep_cif");
130
131 // Note that cif retains references to args and result,
132 // which is why we hold onto them here.
133 Cif { cif, args, result }
134 }
135
136 /// Calls a function with the given arguments.
137 ///
138 /// In particular, this method invokes function `fun` passing it
139 /// arguments `args`, and returns the result.
140 ///
141 /// # Safety
142 ///
143 /// There is no checking that the calling convention and types
144 /// in the `Cif` match the actual calling convention and types of
145 /// `fun`, nor that they match the types of `args`.
146 pub unsafe fn call<R>(&self, fun: CodePtr, args: &[Arg]) -> R {
147 assert_eq!(
148 self.cif.nargs as usize,
149 args.len(),
150 "Cif::call: passed wrong number of arguments"
151 );
152
153 low::call::<R>(
154 &self.cif as *const _ as *mut _,
155 fun,
156 args.as_ptr() as *mut *mut c_void,
157 )
158 }
159
160 /// Sets the CIF to use the given calling convention.
161 pub fn set_abi(&mut self, abi: FfiAbi) {
162 self.cif.abi = abi;
163 }
164
165 /// Gets a raw pointer to the underlying [`low::ffi_cif`].
166 ///
167 /// This can be used for passing a `middle::Cif` to functions from the
168 /// [`low`](crate::low) and [`raw`](crate::raw) modules.
169 pub fn as_raw_ptr(&self) -> *mut low::ffi_cif {
170 &self.cif as *const _ as *mut _
171 }
172}
173
174/// Represents a closure callable from C.
175///
176/// A libffi closure captures a `void*` (“userdata”) and passes it to a
177/// callback when the code pointer (obtained via [`Closure::code_ptr`])
178/// is invoked. Lifetype parameter `'a` ensures that the closure does
179/// not outlive the userdata.
180///
181/// Construct with [`Closure::new`] and [`Closure::new_mut`].
182///
183/// # Examples
184///
185/// In this example we turn a Rust lambda into a C function. We first
186/// define function `lambda_callback`, which will be called by libffi
187/// when the closure is called. The callback function takes four
188/// arguments: a CIF describing its arguments, a pointer for where to
189/// store its result, a pointer to an array of pointers to its
190/// arguments, and a userdata pointer. In this ase, the Rust closure
191/// value `lambda` is passed as userdata to `lambda_callback`, which
192/// then invokes it.
193///
194/// ```
195/// use std::mem;
196/// use std::os::raw::c_void;
197///
198/// use libffi::middle::*;
199/// use libffi::low;
200///
201/// unsafe extern "C" fn lambda_callback<F: Fn(u64, u64) -> u64>(
202/// _cif: &low::ffi_cif,
203/// result: &mut u64,
204/// args: *const *const c_void,
205/// userdata: &F)
206/// {
207/// let args = args as *const &u64;
208/// let arg1 = **args.offset(0);
209/// let arg2 = **args.offset(1);
210///
211/// *result = userdata(arg1, arg2);
212/// }
213///
214/// let cif = Cif::new(vec![Type::u64(), Type::u64()].into_iter(),
215/// Type::u64());
216/// let lambda = |x: u64, y: u64| x + y;
217/// let closure = Closure::new(cif, lambda_callback, &lambda);
218///
219/// let fun: &extern "C" fn(u64, u64) -> u64 = unsafe {
220/// closure.instantiate_code_ptr()
221/// };
222///
223/// assert_eq!(11, fun(5, 6));
224/// assert_eq!(12, fun(5, 7));
225/// ```
226#[derive(Debug)]
227pub struct Closure<'a> {
228 _cif: Box<Cif>,
229 alloc: *mut low::ffi_closure,
230 code: CodePtr,
231 _marker: PhantomData<&'a ()>,
232}
233
234impl<'a> Drop for Closure<'a> {
235 fn drop(&mut self) {
236 unsafe {
237 low::closure_free(self.alloc);
238 }
239 }
240}
241
242impl<'a> Closure<'a> {
243 /// Creates a new closure with immutable userdata.
244 ///
245 /// # Arguments
246 ///
247 /// - `cif` — describes the calling convention and argument and
248 /// result types
249 /// - `callback` — the function to call when the closure is invoked
250 /// - `userdata` — the pointer to pass to `callback` along with the
251 /// arguments when the closure is called
252 ///
253 /// # Result
254 ///
255 /// The new closure.
256 pub fn new<U, R>(cif: Cif, callback: Callback<U, R>, userdata: &'a U) -> Self {
257 let cif = Box::new(cif);
258 let (alloc, code) = low::closure_alloc();
259
260 unsafe {
261 low::prep_closure(
262 alloc,
263 cif.as_raw_ptr(),
264 callback,
265 userdata as *const U,
266 code,
267 )
268 .unwrap();
269 }
270
271 Closure {
272 _cif: cif,
273 alloc,
274 code,
275 _marker: PhantomData,
276 }
277 }
278
279 /// Creates a new closure with mutable userdata.
280 ///
281 /// # Arguments
282 ///
283 /// - `cif` — describes the calling convention and argument and
284 /// result types
285 /// - `callback` — the function to call when the closure is invoked
286 /// - `userdata` — the pointer to pass to `callback` along with the
287 /// arguments when the closure is called
288 ///
289 /// # Result
290 ///
291 /// The new closure.
292 pub fn new_mut<U, R>(cif: Cif, callback: CallbackMut<U, R>, userdata: &'a mut U) -> Self {
293 let cif = Box::new(cif);
294 let (alloc, code) = low::closure_alloc();
295
296 unsafe {
297 low::prep_closure_mut(alloc, cif.as_raw_ptr(), callback, userdata as *mut U, code)
298 .unwrap();
299 }
300
301 Closure {
302 _cif: cif,
303 alloc,
304 code,
305 _marker: PhantomData,
306 }
307 }
308
309 /// Obtains the callable code pointer for a closure.
310 ///
311 /// # Safety
312 ///
313 /// The result needs to be transmuted to the correct type before
314 /// it can be called. If the type is wrong then undefined behavior
315 /// will result.
316 pub fn code_ptr(&self) -> &unsafe extern "C" fn() {
317 self.code.as_fun()
318 }
319
320 /// Transmutes the callable code pointer for a closure to a reference
321 /// to any type. This is intended to be used to transmute it to its
322 /// correct function type in order to call it.
323 ///
324 /// # Safety
325 ///
326 /// This method allows transmuting to a reference to *any* sized type,
327 /// and cannot check whether the code pointer actually has that type.
328 /// If the type is wrong then undefined behavior will result.
329 pub unsafe fn instantiate_code_ptr<T>(&self) -> &T {
330 self.code.as_any_ref_()
331 }
332}
333
334/// The type of callback invoked by a [`ClosureOnce`].
335pub type CallbackOnce<U, R> = CallbackMut<Option<U>, R>;
336
337/// A closure that owns needs-drop data.
338///
339/// This allows the closure’s callback to take ownership of the data, in
340/// which case the userdata will be gone if called again.
341#[derive(Debug)]
342pub struct ClosureOnce {
343 alloc: *mut low::ffi_closure,
344 code: CodePtr,
345 _cif: Box<Cif>,
346 _userdata: Box<dyn Any>,
347}
348
349impl Drop for ClosureOnce {
350 fn drop(&mut self) {
351 unsafe {
352 low::closure_free(self.alloc);
353 }
354 }
355}
356
357impl ClosureOnce {
358 /// Creates a new closure with owned userdata.
359 ///
360 /// # Arguments
361 ///
362 /// - `cif` — describes the calling convention and argument and
363 /// result types
364 /// - `callback` — the function to call when the closure is invoked
365 /// - `userdata` — the value to pass to `callback` along with the
366 /// arguments when the closure is called
367 ///
368 /// # Result
369 ///
370 /// The new closure.
371 pub fn new<U: Any, R>(cif: Cif, callback: CallbackOnce<U, R>, userdata: U) -> Self {
372 let _cif = Box::new(cif);
373 let _userdata = Box::new(Some(userdata)) as Box<dyn Any>;
374 let (alloc, code) = low::closure_alloc();
375
376 assert!(!alloc.is_null(), "closure_alloc: returned null");
377
378 {
379 let borrow = _userdata.downcast_ref::<Option<U>>().unwrap();
380 unsafe {
381 low::prep_closure_mut(
382 alloc,
383 _cif.as_raw_ptr(),
384 callback,
385 borrow as *const _ as *mut _,
386 code,
387 )
388 .unwrap();
389 }
390 }
391
392 ClosureOnce {
393 alloc,
394 code,
395 _cif,
396 _userdata,
397 }
398 }
399
400 /// Obtains the callable code pointer for a closure.
401 ///
402 /// # Safety
403 ///
404 /// The result needs to be transmuted to the correct type before
405 /// it can be called. If the type is wrong then undefined behavior
406 /// will result.
407 pub fn code_ptr(&self) -> &unsafe extern "C" fn() {
408 self.code.as_fun()
409 }
410
411 /// Transmutes the callable code pointer for a closure to a reference
412 /// to any type. This is intended to be used to transmute it to its
413 /// correct function type in order to call it.
414 ///
415 /// # Safety
416 ///
417 /// This method allows transmuting to a reference to *any* sized type,
418 /// and cannot check whether the code pointer actually has that type.
419 /// If the type is wrong then undefined behavior will result.
420 pub unsafe fn instantiate_code_ptr<T>(&self) -> &T {
421 self.code.as_any_ref_()
422 }
423}
424
425#[cfg(test)]
426mod test {
427 use super::*;
428 use crate::low;
429 use std::os::raw::c_void;
430
431 #[test]
432 fn call() {
433 let cif = Cif::new(vec![Type::i64(), Type::i64()].into_iter(), Type::i64());
434 let f = |m: i64, n: i64| -> i64 {
435 unsafe { cif.call(CodePtr(add_it as *mut c_void), &[arg(&m), arg(&n)]) }
436 };
437
438 assert_eq!(12, f(5, 7));
439 assert_eq!(13, f(6, 7));
440 assert_eq!(15, f(8, 7));
441 }
442
443 extern "C" fn add_it(n: i64, m: i64) -> i64 {
444 n + m
445 }
446
447 #[test]
448 fn closure() {
449 let cif = Cif::new(vec![Type::u64()].into_iter(), Type::u64());
450 let env: u64 = 5;
451 let closure = Closure::new(cif, callback, &env);
452
453 let fun: &extern "C" fn(u64) -> u64 = unsafe { closure.instantiate_code_ptr() };
454
455 assert_eq!(11, fun(6));
456 assert_eq!(12, fun(7));
457 }
458
459 unsafe extern "C" fn callback(
460 _cif: &low::ffi_cif,
461 result: &mut u64,
462 args: *const *const c_void,
463 userdata: &u64,
464 ) {
465 let args = args as *const &u64;
466 *result = **args + *userdata;
467 }
468
469 #[test]
470 fn rust_lambda() {
471 let cif = Cif::new(vec![Type::u64(), Type::u64()].into_iter(), Type::u64());
472 let env = |x: u64, y: u64| x + y;
473 let closure = Closure::new(cif, callback2, &env);
474
475 let fun: &extern "C" fn(u64, u64) -> u64 = unsafe { closure.instantiate_code_ptr() };
476
477 assert_eq!(11, fun(5, 6));
478 }
479
480 unsafe extern "C" fn callback2<F: Fn(u64, u64) -> u64>(
481 _cif: &low::ffi_cif,
482 result: &mut u64,
483 args: *const *const c_void,
484 userdata: &F,
485 ) {
486 let args = args as *const &u64;
487 let arg1 = **args.offset(0);
488 let arg2 = **args.offset(1);
489
490 *result = userdata(arg1, arg2);
491 }
492
493 #[test]
494 fn clone_cif() {
495 let cif = Cif::new(
496 vec![
497 Type::structure(vec![
498 Type::structure(vec![Type::u64(), Type::u8(), Type::f64()]),
499 Type::i8(),
500 Type::i64(),
501 ]),
502 Type::u64(),
503 ]
504 .into_iter(),
505 Type::u64(),
506 );
507 let clone_cif = cif.clone();
508
509 unsafe {
510 let args = std::slice::from_raw_parts(cif.cif.arg_types, cif.cif.nargs as usize);
511 let struct_arg = args
512 .first()
513 .expect("CIF arguments slice was empty")
514 .as_ref()
515 .expect("CIF first argument was null");
516 // Get slice of length 1 to get the first element
517 let struct_size = struct_arg.size;
518 let struct_parts = std::slice::from_raw_parts(struct_arg.elements, 1);
519 let substruct_size = struct_parts
520 .first()
521 .expect("CIF struct argument's elements slice was empty")
522 .as_ref()
523 .expect("CIF struct argument's first element was null")
524 .size;
525
526 let clone_args =
527 std::slice::from_raw_parts(clone_cif.cif.arg_types, clone_cif.cif.nargs as usize);
528 let clone_struct_arg = clone_args
529 .first()
530 .expect("CIF arguments slice was empty")
531 .as_ref()
532 .expect("CIF first argument was null");
533 // Get slice of length 1 to get the first element
534 let clone_struct_size = clone_struct_arg.size;
535 let clone_struct_parts = std::slice::from_raw_parts(clone_struct_arg.elements, 1);
536 let clone_substruct_size = clone_struct_parts
537 .first()
538 .expect("Cloned CIF struct argument's elements slice was empty")
539 .as_ref()
540 .expect("Cloned CIF struct argument's first element was null")
541 .size;
542
543 assert_eq!(struct_size, clone_struct_size);
544 assert_eq!(substruct_size, clone_substruct_size);
545 }
546 }
547}
548