Crates.io | ffi_trait |
lib.rs | ffi_trait |
version | 0.1.1 |
source | src |
created_at | 2024-07-21 05:21:24.800167 |
updated_at | 2024-07-21 08:15:02.860551 |
description | An attribute that makes an FFI-safe `dyn Trait` |
homepage | |
repository | |
max_upload_size | |
id | 1310119 |
size | 10,781 |
ffi_trait
This crate has a #[ffi_trait]
attribute that will generate an FFI-compatible struct for passing around trait objects
A trait like
#[ffi_trait]
pub trait Foo {
fn a(&self);
fn b(&self, x: i32) -> i32;
}
will turn into
#[derive(::core::clone::Clone, ::core::marker::Copy)]
#[repr(transparent)]
struct FfiDynFooSelf<'_self> {
ptr: ::core::ptr::NonNull<()>,
_data: ::core::marker::PhantomData<&'_self ()>,
}
#[repr(C)]
pub struct FfiDynFoo<'_self> {
ptr: FfiDynFooSelf<'_self>,
vtable: *const FfiDynFooVtable,
_generics: ::core::marker::PhantomData<()>,
}
impl<'_self> FfiDynFoo<'_self> {
fn new<_Self: Foo>(value: &'_self mut _Self) -> Self {
Self {
ptr: FfiDynFooSelf {
ptr: ::core::ptr::NonNull::from(value).cast(),
_data: ::core::marker::PhantomData,
},
vtable: &const { <FfiDynFooVtable>::new::<_Self>() },
_generics: ::core::marker::PhantomData,
}
}
}
impl<'_self> FfiDynFoo<'_self> {
fn a(&self) {
unsafe { ((*self.vtable).a)(self.ptr) }
}
fn b(&self, _1: i32) -> i32 {
unsafe { ((*self.vtable).b)(self.ptr, _1) }
}
}
#[repr(C)]
struct FfiDynFooVtable {
a: unsafe extern "C" fn(this: FfiDynFooSelf),
b: unsafe extern "C" fn(this: FfiDynFooSelf, _1: i32) -> i32,
_generics: ::core::marker::PhantomData<()>,
}
impl FfiDynFooVtable {
const fn new<_Self: Foo>() -> Self {
// some wrapper `extern "C"` methods
}
}