#[ffi]Expand description
Wrap an impl block with #[ffi(...)] to generate FFI functions for all methods in the impl
block.
§Arguments
The impl-level ffi attribute accepts the following parameters:
mod_name: The name of the module to create to contain the FFI functions. Defaults to the name of the type being implemented, converted to lowercase. For examplename = "vec3_mod".visibility: The visibility of the module to create to contain the FFI functions. Defaults topub. For examplevisibility = "pub(crate)".self_ty: The self type to use for the receiver argument for all methods. Defaults to a mut pointer to the type being implemented. For exampleself_ty = "*mut std::ffi::c_void".expect: If the method returns aResult, whether to call.expecton the result. Defaults tofalse. For exampleexpect.from_ptr: Whether to generateFrom<T>where T is the type specified inself_ty. Defaults tofalse. For examplefrom_ptr. If not specified, a manual implementation must be provided.from_any_ptr: Whether to generateFrom<*mut T>. Defaults tofalse. For examplefrom_any_ptr. If not specified, a manual implementation must be provided.
For example, an impl-level attribute specifying that a public module named my_ffi_mod,
containing FFI functions for all methods in the Vec3 impl block, should be generated,
with the receiver type *mut std::ffi::c_void and that methods which return a Result
should be .expect-ed and a From<*mut std::ffi::c_void> implementation should be
generated, would look like:
#[ffi(mod_name = "my_ffi_mod", self_ty = "*mut std::ffi::c_void", expect, from_ptr)]The method-level ffi attribute accepts the following parameters:
expect: If the method returns aResult, whether to call.expecton the result. Defaults tofalse. For exampleexpect. If not specified on theimpllevel attribute, the module level attribute takes precedence.visibility: The visibility of the generated FFI function. Defaults topub. For examplevisibility = "pub(crate)".name: The name of the generated FFI function. Defaults to the name of the method being implemented. For examplename = "vec3_add".arg: Can be specified multiple times. The arguments to the generated FFI function.
For example, a method-level attribute specifying that a public FFI function named
vec3_add should be generated, which takes its receiver as the last argument and that
methods which return a Result should be .expect-ed, would look like:
#[ffi(arg(), arg(), arg(), arg(self), expect, name = "vec3_add")]
fn vec3_add(&mut self, x: i32, y: i32, z: i32) { /* */ }The argument-level arg attribute accepts the following parameters:
self: Whether this argument needs to be converted to the receiver type. Defaults tofalse. For exampleself.rest: Whether this argument is the rest of the arguments. Defaults tofalse. Afterrestis specified, no otherargattributes may be specified.ty: The type to convert this argument to. Defaults to the type of the argument. For examplety = "i32". A validFromimplementation must exist for this type.rename: The name of the argument in the generated FFI function. Defaults to the name of the argument. For examplerename = "x".
An empty arg() specifies only the position of an argument. In the following example, we
specify that the FFI function should receive the first three non-receiver arguments, then
the receiver argument.
#[ffi(arg(), arg(), arg(), arg(self))]
fn vec3_add(&mut self, x: i32, y: i32, z: i32) { /* */ }This is equivalent to:
#[ffi(arg(rest), arg(self))]
fn vec3_add(&mut self, x: i32, y: i32, z: i32) { /* */ }Likewise:
#[ffi(arg(self), arg(), arg(), arg())]
fn vec3_add(&mut self, x: i32, y: i32, z: i32) { /* */ }is equivalent to:
#[ffi(arg(self), arg(rest))]
fn vec3_add(&mut self, x: i32, y: i32, z: i32) { /* */ }§Example
The simple use case, where a callback we specify is called with user data we specify.
use ffi::ffi;
extern "C" fn run_callback(
callback: extern "C" fn(*mut std::ffi::c_void, i32, i32, i32) -> i32,
data: *mut std::ffi::c_void,
) -> i32 {
callback(data, 1, 2, 3)
}
#[derive(Debug, Clone, PartialEq, Eq)]
struct Vec3 {
x: i32,
y: i32,
z: i32,
}
#[ffi(from_ptr, self_ty = "*mut std::ffi::c_void")]
impl Vec3 {
#[ffi(arg(self), arg(rest))]
fn add(&mut self, x: i32, y: i32, z: i32) -> i32 {
self.x += x;
self.y += y;
self.z += z;
self.x + self.y + self.z
}
}
fn main() {
let mut v = Vec3 { x: 1, y: 2, z: 3 };
run_callback(vec3::add, &mut v as *mut Vec3 as *mut _);
assert_eq!(v, Vec3 { x: 2, y: 4, z: 6 })
}