pub struct Function { /* private fields */ }Expand description
An callable FFI function.
Function can be used to call FFI functions in cases where the signature is not known at
compile-time.
§Example
use fiffi::function::{Function, arg, ret};
use fiffi::types::Type;
extern "C" fn double(value: i32) -> i32 {
value * 2
}
let fn_ptr = fiffi::fn_ptrize!(double);
let function = Function::new(fn_ptr, &[Type::I32], Some(&Type::I32));
let input = 21i32;
let mut output = 0i32;
// SAFETY: The function signature used to construct `function` matches `double`.
unsafe {
function.call([arg(&input)], ret(&mut output));
}
assert_eq!(output, 42);Implementations§
Source§impl Function
impl Function
Sourcepub fn new<'args, I>(
fn_ptr: FnPtr,
argument_types: I,
return_type: Option<&Type>,
) -> Selfwhere
I: IntoIterator<Item = &'args Type>,
pub fn new<'args, I>(
fn_ptr: FnPtr,
argument_types: I,
return_type: Option<&Type>,
) -> Selfwhere
I: IntoIterator<Item = &'args Type>,
Create a Function using the target’s default ABI.
§Warning
libffi stores the number of arguments in a C unsigned int. If more than c_uint::MAX
argument types are provided, only the first c_uint::MAX are retained in the prepared
function signature.
Sourcepub fn variadic<'fixed_args, 'variadic_args, I1, I2>(
fn_ptr: FnPtr,
fixed_argument_types: I1,
variadic_argument_types: I2,
return_type: Option<&Type>,
) -> Selfwhere
I1: IntoIterator<Item = &'fixed_args Type>,
I2: IntoIterator<Item = &'variadic_args VariadicType>,
pub fn variadic<'fixed_args, 'variadic_args, I1, I2>(
fn_ptr: FnPtr,
fixed_argument_types: I1,
variadic_argument_types: I2,
return_type: Option<&Type>,
) -> Selfwhere
I1: IntoIterator<Item = &'fixed_args Type>,
I2: IntoIterator<Item = &'variadic_args VariadicType>,
Create a variadic Function using the target’s default ABI.
fixed_argument_types must describe the fixed parameters, and variadic_argument_types
must describe the variadic arguments supplied for a call.
§Warning
libffi stores the number of arguments in a C unsigned int. If more than c_uint::MAX
argument types are provided, only the first c_uint::MAX are retained in the prepared
function signature.
Fixed arguments are retained before variadic arguments if the signature is truncated.
§Example
use std::ffi::c_char;
use fiffi::function::{Function, arg, ret};
use fiffi::types::{Type, VariadicType};
#[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;
}
let function = Function::variadic(
fiffi::fn_ptrize!(snprintf),
// Fixed arguments
//Output buffer Buffer size Format string
&[Type::Pointer, Type::Usize, Type::Pointer],
// Variadic arguments
&[VariadicType::I32],
Some(&Type::I32),
);
let format = c"Num: %d";
let num = 1337i32;
let expected = c"Num: 1337".to_bytes_with_nul();
let mut output_buffer = [0u8; 128];
let mut return_value = 0i32;
// SAFETY: `function` was built with a valid `snprintf` function pointer and the correct
// function signature for `snprintf` with a single `i32` variadic argument.
unsafe {
function.call(
[
arg(&output_buffer.as_mut_ptr()),
arg(&output_buffer.len()),
arg(&format),
arg(&num),
],
ret(&mut return_value),
);
}
// `snprintf`'s return value return the written length without the final NULL byte.
assert_eq!(return_value as usize, expected.len() - 1);
assert_eq!(expected, &output_buffer[0..expected.len()]);Sourcepub fn with_abi<'args, I>(
fn_ptr: FnPtr,
argument_types: I,
return_type: Option<&Type>,
abi: Abi,
) -> Selfwhere
I: IntoIterator<Item = &'args Type>,
pub fn with_abi<'args, I>(
fn_ptr: FnPtr,
argument_types: I,
return_type: Option<&Type>,
abi: Abi,
) -> Selfwhere
I: IntoIterator<Item = &'args Type>,
Sourcepub fn variadic_with_abi<'fixed_args, 'variadic_args, I1, I2>(
fn_ptr: FnPtr,
fixed_argument_types: I1,
variadic_argument_types: I2,
return_type: Option<&Type>,
abi: Abi,
) -> Selfwhere
I1: IntoIterator<Item = &'fixed_args Type>,
I2: IntoIterator<Item = &'variadic_args VariadicType>,
pub fn variadic_with_abi<'fixed_args, 'variadic_args, I1, I2>(
fn_ptr: FnPtr,
fixed_argument_types: I1,
variadic_argument_types: I2,
return_type: Option<&Type>,
abi: Abi,
) -> Selfwhere
I1: IntoIterator<Item = &'fixed_args Type>,
I2: IntoIterator<Item = &'variadic_args VariadicType>,
Creates a variadic Function using the provided Abi.
fixed_argument_types must describe the fixed parameters, and variadic_argument_types
must describe the variadic arguments supplied for a call.
§Warning
libffi stores the number of arguments in a C unsigned int. If more than c_uint::MAX
argument types are provided, only the first c_uint::MAX are retained in the prepared
function signature.
Fixed arguments are retained before variadic arguments if the signature is truncated.
Sourcepub fn builder() -> FunctionBuilder<FnPtrNotSet>
pub fn builder() -> FunctionBuilder<FnPtrNotSet>
Create a FunctionBuilder used to build a Function.
§Example
use fiffi::function::Function;
use fiffi::types::Type;
extern "C" fn add(a: i32, b: i64) -> i64 {
i64::from(a) + b
}
let function = Function::builder()
.arg(Type::I32)
.arg(Type::I64)
.ret(Some(Type::I64))
.fn_ptr(fiffi::fn_ptrize!(add))
.build();Sourcepub fn variadic_builder() -> VariadicFunctionBuilder<FnPtrNotSet>
pub fn variadic_builder() -> VariadicFunctionBuilder<FnPtrNotSet>
Create a VariadicFunctionBuilder used to build a variadic Function.
Sourcepub unsafe fn call<'arg, I>(&self, args: I, ret: Ret<'_>)where
I: IntoIterator<Item = Arg<'arg>>,
pub unsafe fn call<'arg, I>(&self, args: I, ret: Ret<'_>)where
I: IntoIterator<Item = Arg<'arg>>,
Calls the wrapped function pointer through libffi.
§Safety
- The wrapped
FnPtrmust be valid to call with this function’s ABI and signature. - Every
Arginargsmust point to an initialized value matching the correspondingTypethe function expects and remain alive for the duration of the call. - All arguments expected by the called function must be provided.
retmust be valid to write the return type to, unless the function was created with no return type.- Calling the target function must not violate Rust aliasing rules for any referenced memory.
If more than c_uint::MAX argument types were provided during construction, libffi will use
the truncated signature and may not read every argument pointer provided in args.
§Example
use fiffi::function::{Function, arg, ret};
use fiffi::types::Type;
extern "C" fn add_one(value: i32) -> i32 {
value + 1
}
let function = Function::new(fiffi::fn_ptrize!(add_one), &[Type::I32], Some(&Type::I32));
let input = 41i32;
let mut output = 0i32;
// SAFETY: The function pointer, argument type, return type, and storage match `add_one`.
unsafe {
function.call([arg(&input)], ret(&mut output));
}
assert_eq!(output, 42);Sourcepub fn argument_layouts(&self) -> Vec<FfiTypeLayout>
pub fn argument_layouts(&self) -> Vec<FfiTypeLayout>
Returns the memory layout of this Function’s arguments.
§Example
use fiffi::function::Function;
use fiffi::types::Type;
extern "C" fn identity(value: i32) -> i32 {
value
}
let function = Function::new(fiffi::fn_ptrize!(identity), &[Type::I32], Some(&Type::I32));
assert_eq!(function.argument_layouts(), vec![Type::I32.layout()]);Sourcepub fn return_layout(&self) -> FfiTypeLayout
pub fn return_layout(&self) -> FfiTypeLayout
Returns the memory layout of this Function’s return value.
§Example
use fiffi::function::Function;
use fiffi::types::Type;
extern "C" fn identity(value: i32) -> i32 {
value
}
let function = Function::new(fiffi::fn_ptrize!(identity), &[Type::I32], Some(&Type::I32));
assert_eq!(function.return_layout(), Type::I32.layout());