#![cfg_attr(feature = "closure", doc = "[`Closure`]: `crate::closure::Closure`")]
#![cfg_attr(
feature = "closure",
doc = "[`DynamicClosure`]: `crate::closure::DynamicClosure`"
)]
#![cfg_attr(not(feature = "closure"), doc = "[`Closure`]: #features")]
#![cfg_attr(not(feature = "closure"), doc = "[`DynamicClosure`]: #features")]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(not(test), no_std)]
pub mod abi;
#[cfg(feature = "closure")]
pub mod closure;
pub mod errors;
pub mod function;
pub mod types;
mod fn_ptr;
pub use fn_ptr::FnPtr;
pub(crate) mod raw;
pub(crate) mod return_buffer;
#[cfg(msan)]
unsafe extern "C" {
pub(crate) unsafe fn __msan_unpoison(addr: *const core::ffi::c_void, size: usize);
pub(crate) unsafe fn __msan_poison(addr: *const core::ffi::c_void, size: usize);
pub(crate) unsafe fn __msan_test_shadow(addr: *const core::ffi::c_void, size: usize) -> isize;
}
#[cfg(test)]
pub(crate) mod test_utils {
use core::ffi::{CStr, c_char, c_void};
use core::ptr::null_mut;
use libffi_sys::{FFI_TYPE_STRUCT, ffi_type};
use crate::raw::{ffi_type_uint8, ffi_type_uint64};
use crate::types::{FfiType, Type};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct TestStruct(pub u8, pub u64, pub u64, pub u64, pub u64);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct PointerStruct(pub *const c_void);
unsafe impl Send for PointerStruct {}
unsafe impl Sync for PointerStruct {}
unsafe impl FfiType for TestStruct {
fn ffi_type() -> Type {
unsafe {
Type::create_struct_unchecked(vec![
Type::U8,
Type::U64,
Type::U64,
Type::U64,
Type::U64,
])
}
}
}
pub static mut TEST_STRUCT_MEMBERS: [*mut ffi_type; 6] = [
&raw mut ffi_type_uint8,
&raw mut ffi_type_uint64,
&raw mut ffi_type_uint64,
&raw mut ffi_type_uint64,
&raw mut ffi_type_uint64,
null_mut(),
];
pub static I8_ARG: i8 = 0x11;
pub static U8_ARG: u8 = 0x22;
pub static I16_ARG: i16 = 0x3333;
pub static U16_ARG: u16 = 0x4444;
pub static I32_ARG: i32 = 0x5555_5555;
pub static U32_ARG: u32 = 0x6666_6666;
pub static I64_ARG: i64 = 0x7777_7777_7777_7777;
pub static U64_ARG: u64 = 0x8888_8888_8888_8888;
#[expect(
clippy::cast_possible_truncation,
reason = "Truncating is not a problem in this instance as we are comparing the argument with `ISIZE_ARG` anyways."
)]
pub static ISIZE_ARG: isize = I64_ARG as isize;
#[expect(
clippy::cast_possible_truncation,
reason = "Truncating is not a problem in this instance as we are comparing the argument with `USIZE_ARG` anyways."
)]
pub static USIZE_ARG: usize = U64_ARG as usize;
pub static F32_ARG: f32 = core::f32::consts::PI;
pub static F64_ARG: f64 = core::f64::consts::E;
pub static PTR_ARG: PointerStruct = PointerStruct((&raw const U32_ARG).cast());
pub static STRUCT_ARG: TestStruct = TestStruct(
0x77,
0x9999_9999_9999_9999,
0xAAAA_AAAA_AAAA_AAAA,
0xBBBB_BBBB_BBBB_BBBB,
0xCCCC_CCCC_CCCC_CCCC,
);
pub static SNPRINTF_FORMAT: &CStr = c"1: %d, 2: %u, 3: %lld, 4: %llu, 5: \"%s\", 6: %.1f.\n";
pub static SNPRINTF_ARG_1: i32 = 1_234_567;
pub static SNPRINTF_ARG_2: u32 = 9_876_543;
pub static SNPRINTF_ARG_3: i64 = 12_345_678_900;
pub static SNPRINTF_ARG_4: u64 = 98_765_432_100;
pub static SNPRINTF_ARG_5: &CStr = c"This is a &CStr";
pub static SNPRINTF_ARG_6: f64 = 1.0;
pub static SNPRINTF_EXPECTED_OUTPUT: &CStr = c"1: 1234567, 2: 9876543, 3: 12345678900, 4: 98765432100, 5: \"This is a &CStr\", 6: 1.0.\n";
pub static SNPRINTF_EXPECTED_RETURN_VALUE: i32 = 86;
pub fn get_test_struct_ffi_type() -> ffi_type {
ffi_type {
type_: FFI_TYPE_STRUCT,
elements: (&raw mut TEST_STRUCT_MEMBERS).cast(),
..Default::default()
}
}
#[cfg_attr(target_env = "msvc", link(name = "legacy_stdio_definitions"))]
unsafe extern "C" {
pub unsafe fn snprintf(s: *mut c_char, n: usize, format: *const c_char, ...) -> i32;
}
}
#[cfg(all(doc, feature = "closure"))]
#[doc(hidden)]
#[doc = include_str!("../README.md")]
mod _readme {}
#[cfg(all(doc, feature = "closure"))]
#[doc(hidden)]
#[doc = include_str!("../libffi-rs-2-fiffi.md")]
mod _libffi_rs_2_fiffi {}