1#![doc(html_root_url = "https://docs.rs/libffi-sys/3.3.3")]
2#![allow(non_camel_case_types)]
49#![allow(non_snake_case)]
50#![allow(non_upper_case_globals)]
51#![allow(improper_ctypes)]
52#![allow(unused_imports)]
53
54use core::ffi::{c_char, c_int, c_long, c_schar, c_uint, c_ulong, c_ushort, c_void};
55use core::fmt::{self, Debug, Formatter};
56use core::mem::zeroed;
57
58mod arch;
59pub use arch::*;
60
61pub type ffi_arg = c_ulong;
63pub type ffi_sarg = c_long;
65pub type ffi_abi = u32;
67pub type ffi_status = u32;
69pub type ffi_type_enum = u32;
70
71pub const FFI_64_BIT_MAX: u64 = 9_223_372_036_854_775_807;
72pub const FFI_CLOSURES: u32 = 1;
73pub const FFI_SIZEOF_ARG: usize = core::mem::size_of::<c_long>();
74pub const FFI_SIZEOF_JAVA_RAW: usize = FFI_SIZEOF_ARG;
76
77pub const FFI_TYPE_VOID: u32 = 0;
78pub const FFI_TYPE_INT: u32 = 1;
79pub const FFI_TYPE_FLOAT: u32 = 2;
80pub const FFI_TYPE_DOUBLE: u32 = 3;
81pub const FFI_TYPE_LONGDOUBLE: u32 = 4;
82pub const FFI_TYPE_UINT8: u32 = 5;
83pub const FFI_TYPE_SINT8: u32 = 6;
84pub const FFI_TYPE_UINT16: u32 = 7;
85pub const FFI_TYPE_SINT16: u32 = 8;
86pub const FFI_TYPE_UINT32: u32 = 9;
87pub const FFI_TYPE_SINT32: u32 = 10;
88pub const FFI_TYPE_UINT64: u32 = 11;
89pub const FFI_TYPE_SINT64: u32 = 12;
90pub const FFI_TYPE_STRUCT: u32 = 13;
91pub const FFI_TYPE_POINTER: u32 = 14;
92pub const FFI_TYPE_COMPLEX: u32 = 15;
93pub const FFI_TYPE_LAST: u32 = 15;
94
95pub const ffi_status_FFI_OK: ffi_status = 0;
96pub const ffi_status_FFI_BAD_TYPEDEF: ffi_status = 1;
97pub const ffi_status_FFI_BAD_ABI: ffi_status = 2;
98pub const ffi_status_FFI_BAD_ARGTYPE: ffi_status = 3;
99
100pub const ffi_type_enum_STRUCT: ffi_type_enum = 13;
101pub const ffi_type_enum_COMPLEX: ffi_type_enum = 15;
102
103#[repr(C)]
152#[derive(Copy, Clone)]
153pub struct ffi_type {
154 pub size: usize,
155 pub alignment: c_ushort,
156 pub type_: c_ushort,
157 pub elements: *mut *mut ffi_type,
158}
159
160impl Default for ffi_type {
161 fn default() -> Self {
162 unsafe { zeroed() }
163 }
164}
165
166#[repr(C)]
171#[derive(Debug, Copy, Clone)]
172pub struct ffi_cif {
173 pub abi: ffi_abi,
174 pub nargs: c_uint,
175 pub arg_types: *mut *mut ffi_type,
176 pub rtype: *mut ffi_type,
177 pub bytes: c_uint,
178 pub flags: c_uint,
179 #[cfg(all(target_arch = "aarch64", target_os = "windows"))]
180 pub is_variadic: c_uint,
181 #[cfg(all(target_arch = "aarch64", target_vendor = "apple"))]
182 pub aarch64_nfixedargs: c_uint,
183 #[cfg(target_arch = "arm")]
184 pub vfp_used: c_int,
185 #[cfg(target_arch = "arm")]
186 pub vfp_reg_free: c_ushort,
187 #[cfg(target_arch = "arm")]
188 pub vfp_nargs: c_ushort,
189 #[cfg(target_arch = "arm")]
190 pub vfp_args: [c_schar; 16],
191 #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
192 pub nfixedargs: c_uint,
193 #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
194 pub riscv_nfixedargs: c_uint,
195 #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
196 pub riscv_unused: c_uint,
197 #[cfg(target_arch = "sparc64")]
198 pub nfixedargs: c_uint,
199 #[cfg(target_arch = "loongarch64")]
200 pub loongarch_nfixedargs: c_uint,
201 #[cfg(target_arch = "loongarch64")]
202 pub loongarch_unused: c_uint,
203 #[cfg(any(
204 target_arch = "mips",
205 target_arch = "mips32r6",
206 target_arch = "mips64",
207 target_arch = "mips64r6"
208 ))]
209 pub mips_nfixedargs: c_uint,
210}
211
212impl Default for ffi_cif {
213 fn default() -> Self {
214 unsafe { zeroed() }
215 }
216}
217
218#[repr(C, align(64))]
219#[derive(Copy, Clone)]
220pub union ffi_raw {
221 pub sint: ffi_sarg,
222 pub uint: ffi_arg,
223 pub flt: f32,
224 pub data: [c_char; FFI_SIZEOF_ARG],
225 pub ptr: *mut c_void,
226}
227
228impl Default for ffi_raw {
229 fn default() -> Self {
230 unsafe { zeroed() }
231 }
232}
233
234pub type ffi_java_raw = ffi_raw;
235
236#[repr(C, align(64))]
237#[derive(Copy, Clone)]
238pub union ffi_trampoline {
239 pub tramp: [c_char; FFI_TRAMPOLINE_SIZE],
240 pub ftramp: *mut c_void,
241}
242
243#[repr(C)]
252#[derive(Copy, Clone)]
253pub struct ffi_closure {
254 pub tramp: ffi_trampoline,
255 pub cif: *mut ffi_cif,
256 pub fun: Option<
257 unsafe extern "C" fn(
258 arg1: *mut ffi_cif,
259 arg2: *mut c_void,
260 arg3: *mut *mut c_void,
261 arg4: *mut c_void,
262 ),
263 >,
264 pub user_data: *mut c_void,
265}
266
267impl Debug for ffi_closure {
269 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
270 f.debug_struct("ffi_closure")
271 .field("tramp", unsafe { &&self.tramp.tramp[..] })
272 .field("cif", &self.cif)
273 .field("fun", &self.fun)
274 .field("user_data", &self.user_data)
275 .finish()
276 }
277}
278
279impl Default for ffi_closure {
280 fn default() -> Self {
281 unsafe { zeroed() }
282 }
283}
284
285#[repr(C)]
286#[derive(Copy, Clone)]
287pub struct ffi_raw_closure {
288 pub tramp: [c_char; FFI_TRAMPOLINE_SIZE],
289 pub cif: *mut ffi_cif,
290 #[cfg(not(target_arch = "x86"))]
292 pub translate_args: Option<
293 unsafe extern "C" fn(
294 arg1: *mut ffi_cif,
295 arg2: *mut c_void,
296 arg3: *mut *mut c_void,
297 arg4: *mut c_void,
298 ),
299 >,
300 #[cfg(not(target_arch = "x86"))]
301 pub this_closure: *mut c_void,
302 pub fun: Option<
303 unsafe extern "C" fn(
304 arg1: *mut ffi_cif,
305 arg2: *mut c_void,
306 arg3: *mut ffi_raw,
307 arg4: *mut c_void,
308 ),
309 >,
310 pub user_data: *mut c_void,
311}
312
313impl Debug for ffi_raw_closure {
315 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
316 let mut debug_struct = f.debug_struct("ffi_raw_closure");
317 debug_struct
318 .field("tramp", &&self.tramp[..])
319 .field("cif", &self.cif);
320
321 #[cfg(not(target_arch = "x86"))]
322 debug_struct.field("translate_args", &self.translate_args);
323 #[cfg(not(target_arch = "x86"))]
324 debug_struct.field("this_closure", &self.this_closure);
325
326 debug_struct
327 .field("fun", &self.fun)
328 .field("user_data", &self.user_data)
329 .finish()
330 }
331}
332
333impl Default for ffi_raw_closure {
334 fn default() -> Self {
335 unsafe { zeroed() }
336 }
337}
338#[repr(C)]
339#[derive(Copy, Clone)]
340pub struct ffi_java_raw_closure {
341 pub tramp: [c_char; FFI_TRAMPOLINE_SIZE],
342 pub cif: *mut ffi_cif,
343 #[cfg(not(target_arch = "x86"))]
345 pub translate_args: Option<
346 unsafe extern "C" fn(
347 arg1: *mut ffi_cif,
348 arg2: *mut c_void,
349 arg3: *mut *mut c_void,
350 arg4: *mut c_void,
351 ),
352 >,
353 #[cfg(not(target_arch = "x86"))]
354 pub this_closure: *mut c_void,
355 pub fun: Option<
356 unsafe extern "C" fn(
357 arg1: *mut ffi_cif,
358 arg2: *mut c_void,
359 arg3: *mut ffi_java_raw,
360 arg4: *mut c_void,
361 ),
362 >,
363 pub user_data: *mut c_void,
364}
365
366impl Debug for ffi_java_raw_closure {
368 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
369 let mut debug_struct = f.debug_struct("ffi_java_raw_closure");
370 debug_struct
371 .field("tramp", &&self.tramp[..])
372 .field("cif", &self.cif);
373
374 #[cfg(not(target_arch = "x86"))]
375 debug_struct.field("translate_args", &self.translate_args);
376 #[cfg(not(target_arch = "x86"))]
377 debug_struct.field("this_closure", &self.this_closure);
378
379 debug_struct
380 .field("fun", &self.fun)
381 .field("user_data", &self.user_data)
382 .finish()
383 }
384}
385
386impl Default for ffi_java_raw_closure {
387 fn default() -> Self {
388 unsafe { zeroed() }
389 }
390}
391
392#[repr(C)]
393#[derive(Debug, Copy, Clone)]
394pub struct ffi_go_closure {
395 pub tramp: *mut c_void,
396 pub cif: *mut ffi_cif,
397 pub fun: Option<
398 unsafe extern "C" fn(
399 arg1: *mut ffi_cif,
400 arg2: *mut c_void,
401 arg3: *mut *mut c_void,
402 arg4: *mut c_void,
403 ),
404 >,
405}
406impl Default for ffi_go_closure {
407 fn default() -> Self {
408 unsafe { zeroed() }
409 }
410}
411
412extern "C" {
413 pub static mut ffi_type_void: ffi_type;
414 pub static mut ffi_type_uint8: ffi_type;
415 pub static mut ffi_type_sint8: ffi_type;
416 pub static mut ffi_type_uint16: ffi_type;
417 pub static mut ffi_type_sint16: ffi_type;
418 pub static mut ffi_type_uint32: ffi_type;
419 pub static mut ffi_type_sint32: ffi_type;
420 pub static mut ffi_type_uint64: ffi_type;
421 pub static mut ffi_type_sint64: ffi_type;
422 pub static mut ffi_type_float: ffi_type;
423 pub static mut ffi_type_double: ffi_type;
424 pub static mut ffi_type_longdouble: ffi_type;
425 pub static mut ffi_type_pointer: ffi_type;
426
427 #[cfg(feature = "complex")]
428 pub static mut ffi_type_complex_float: ffi_type;
429
430 #[cfg(feature = "complex")]
431 pub static mut ffi_type_complex_double: ffi_type;
432
433 #[cfg(feature = "complex")]
434 pub static mut ffi_type_complex_longdouble: ffi_type;
435
436 pub fn ffi_raw_call(
437 cif: *mut ffi_cif,
438 fn_: Option<unsafe extern "C" fn()>,
439 rvalue: *mut c_void,
440 avalue: *mut ffi_raw,
441 );
442
443 pub fn ffi_ptrarray_to_raw(cif: *mut ffi_cif, args: *mut *mut c_void, raw: *mut ffi_raw);
444
445 pub fn ffi_raw_to_ptrarray(cif: *mut ffi_cif, raw: *mut ffi_raw, args: *mut *mut c_void);
446
447 pub fn ffi_raw_size(cif: *mut ffi_cif) -> usize;
448
449 #[cfg(not(target_arch = "x86"))]
451 #[deprecated = "Deprecated in libffi 3.3"]
452 pub fn ffi_java_raw_call(
453 cif: *mut ffi_cif,
454 fn_: Option<unsafe extern "C" fn()>,
455 rvalue: *mut c_void,
456 avalue: *mut ffi_java_raw,
457 );
458
459 #[deprecated = "Deprecated in libffi 3.3"]
460 pub fn ffi_java_ptrarray_to_raw(
461 cif: *mut ffi_cif,
462 args: *mut *mut c_void,
463 raw: *mut ffi_java_raw,
464 );
465
466 #[deprecated = "Deprecated in libffi 3.3"]
467 pub fn ffi_java_raw_to_ptrarray(
468 cif: *mut ffi_cif,
469 raw: *mut ffi_java_raw,
470 args: *mut *mut c_void,
471 );
472
473 #[deprecated = "Deprecated in libffi 3.3"]
474 pub fn ffi_java_raw_size(cif: *mut ffi_cif) -> usize;
475
476 pub fn ffi_closure_alloc(size: usize, code: *mut *mut c_void) -> *mut c_void;
477
478 pub fn ffi_closure_free(arg1: *mut c_void);
479
480 #[deprecated = "Deprecated in libffi 3.3, use `ffi_prep_closure_loc` instead"]
481 pub fn ffi_prep_closure(
482 arg1: *mut ffi_closure,
483 arg2: *mut ffi_cif,
484 fun: Option<
485 unsafe extern "C" fn(
486 arg1: *mut ffi_cif,
487 arg2: *mut c_void,
488 arg3: *mut *mut c_void,
489 arg4: *mut c_void,
490 ),
491 >,
492 user_data: *mut c_void,
493 ) -> ffi_status;
494
495 pub fn ffi_prep_closure_loc(
496 arg1: *mut ffi_closure,
497 arg2: *mut ffi_cif,
498 fun: Option<
499 unsafe extern "C" fn(
500 arg1: *mut ffi_cif,
501 arg2: *mut c_void,
502 arg3: *mut *mut c_void,
503 arg4: *mut c_void,
504 ),
505 >,
506 user_data: *mut c_void,
507 codeloc: *mut c_void,
508 ) -> ffi_status;
509
510 pub fn ffi_prep_raw_closure(
511 arg1: *mut ffi_raw_closure,
512 cif: *mut ffi_cif,
513 fun: Option<
514 unsafe extern "C" fn(
515 arg1: *mut ffi_cif,
516 arg2: *mut c_void,
517 arg3: *mut ffi_raw,
518 arg4: *mut c_void,
519 ),
520 >,
521 user_data: *mut c_void,
522 ) -> ffi_status;
523
524 pub fn ffi_prep_raw_closure_loc(
525 arg1: *mut ffi_raw_closure,
526 cif: *mut ffi_cif,
527 fun: Option<
528 unsafe extern "C" fn(
529 arg1: *mut ffi_cif,
530 arg2: *mut c_void,
531 arg3: *mut ffi_raw,
532 arg4: *mut c_void,
533 ),
534 >,
535 user_data: *mut c_void,
536 codeloc: *mut c_void,
537 ) -> ffi_status;
538
539 #[cfg(not(target_arch = "x86"))]
541 #[deprecated = "Deprecated in libffi 3.3"]
542 pub fn ffi_prep_java_raw_closure(
543 arg1: *mut ffi_java_raw_closure,
544 cif: *mut ffi_cif,
545 fun: Option<
546 unsafe extern "C" fn(
547 arg1: *mut ffi_cif,
548 arg2: *mut c_void,
549 arg3: *mut ffi_java_raw,
550 arg4: *mut c_void,
551 ),
552 >,
553 user_data: *mut c_void,
554 ) -> ffi_status;
555
556 #[cfg(not(target_arch = "x86"))]
558 #[deprecated = "Deprecated in libffi 3.3"]
559 pub fn ffi_prep_java_raw_closure_loc(
560 arg1: *mut ffi_java_raw_closure,
561 cif: *mut ffi_cif,
562 fun: Option<
563 unsafe extern "C" fn(
564 arg1: *mut ffi_cif,
565 arg2: *mut c_void,
566 arg3: *mut ffi_java_raw,
567 arg4: *mut c_void,
568 ),
569 >,
570 user_data: *mut c_void,
571 codeloc: *mut c_void,
572 ) -> ffi_status;
573
574 pub fn ffi_prep_go_closure(
575 arg1: *mut ffi_go_closure,
576 arg2: *mut ffi_cif,
577 fun: Option<
578 unsafe extern "C" fn(
579 arg1: *mut ffi_cif,
580 arg2: *mut c_void,
581 arg3: *mut *mut c_void,
582 arg4: *mut c_void,
583 ),
584 >,
585 ) -> ffi_status;
586
587 pub fn ffi_call_go(
588 cif: *mut ffi_cif,
589 fn_: Option<unsafe extern "C" fn()>,
590 rvalue: *mut c_void,
591 avalue: *mut *mut c_void,
592 closure: *mut c_void,
593 );
594
595 pub fn ffi_prep_cif(
596 cif: *mut ffi_cif,
597 abi: ffi_abi,
598 nargs: c_uint,
599 rtype: *mut ffi_type,
600 atypes: *mut *mut ffi_type,
601 ) -> ffi_status;
602
603 pub fn ffi_prep_cif_var(
604 cif: *mut ffi_cif,
605 abi: ffi_abi,
606 nfixedargs: c_uint,
607 ntotalargs: c_uint,
608 rtype: *mut ffi_type,
609 atypes: *mut *mut ffi_type,
610 ) -> ffi_status;
611
612 pub fn ffi_call(
613 cif: *mut ffi_cif,
614 fn_: Option<unsafe extern "C" fn()>,
615 rvalue: *mut c_void,
616 avalue: *mut *mut c_void,
617 );
618
619 pub fn ffi_get_struct_offsets(
620 abi: ffi_abi,
621 struct_type: *mut ffi_type,
622 offsets: *mut usize,
623 ) -> ffi_status;
624}
625
626#[cfg(test)]
627mod test {
628 use std::{mem::transmute, ptr::addr_of_mut};
629
630 use super::*;
631
632 extern "C" fn cast_u8_u32(x: u8) -> u32 {
633 x as u32
634 }
635
636 #[test]
637 fn test_function_sign_extension() {
638 unsafe {
639 let mut cif: ffi_cif = Default::default();
640 let mut arg_types: Vec<*mut ffi_type> = vec![addr_of_mut!(ffi_type_uint8)];
641
642 let prep_status = ffi_prep_cif(
643 &mut cif,
644 ffi_abi_FFI_DEFAULT_ABI,
645 1,
646 addr_of_mut!(ffi_type_uint8),
647 arg_types.as_mut_ptr(),
648 );
649
650 assert_eq!(prep_status, ffi_status_FFI_OK);
651
652 let mut rval: ffi_arg = 0;
653 let func = transmute::<extern "C" fn(u8) -> u32, extern "C" fn()>(cast_u8_u32);
654
655 ffi_call(
656 &mut cif,
657 Some(func),
658 &mut rval as *mut _ as *mut c_void,
659 vec![&mut 256 as *mut _ as *mut c_void].as_mut_ptr(),
660 );
661
662 assert_eq!(rval, 0);
663 }
664 }
665
666 extern "C" fn add(x: u64, y: u64) -> u64 {
667 x + y
668 }
669
670 #[test]
671 fn test_function_with_two_arguments() {
672 unsafe {
673 let mut cif: ffi_cif = Default::default();
674 let mut arg_types: Vec<*mut ffi_type> =
675 vec![addr_of_mut!(ffi_type_uint64), addr_of_mut!(ffi_type_uint64)];
676
677 let prep_status = ffi_prep_cif(
678 &mut cif,
679 ffi_abi_FFI_DEFAULT_ABI,
680 2,
681 addr_of_mut!(ffi_type_uint64),
682 arg_types.as_mut_ptr(),
683 );
684
685 assert_eq!(prep_status, ffi_status_FFI_OK);
686
687 let mut rval = 0u64;
688 let func = transmute::<extern "C" fn(u64, u64) -> u64, extern "C" fn()>(add);
689
690 ffi_call(
691 &mut cif,
692 Some(func),
693 &mut rval as *mut _ as *mut c_void,
694 vec![
695 &mut 4u64 as *mut _ as *mut c_void,
696 &mut 5u64 as *mut _ as *mut c_void,
697 ]
698 .as_mut_ptr(),
699 );
700
701 assert_eq!(rval, 9);
702 }
703 }
704}