#traits #object #attributes #struct #dyn #vtable

ffi_trait

一个使动态特质 dyn Trait 成为FFI安全的属性

2个版本

0.1.1 2024年7月21日
0.1.0 2024年7月21日

#292过程宏

Download history 211/week @ 2024-07-21 18/week @ 2024-07-28

每月下载 229次

MIT 许可证

11KB
183

ffi_trait

此crate有一个 #[ffi_trait] 属性,该属性将生成一个FFI兼容的结构体,用于传递特质对象

一个像这样的特质

#[ffi_trait]
pub trait Foo {
    fn a(&self);
    fn b(&self, x: i32) -> i32;
}

将转换为

#[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
    }
}

依赖关系

~285–740KB
~18K SLoC