[英]Pass a Rust trait to C
我正在構建一個Rust庫,需要使用Rust對象調用一些C函數。 我有一個帶有調用C函數的函數的特性,C函數在Rust中定義如下:
extern {
fn process_trait(my_trait: MyTrait);
}
這個想法是用戶可以為他的struct實現trait,然后調用C函數(基本上,C然后調用其他一些Rust,它會調用一些Trait函數)。 這里的錯誤是: the trait core::marker::Sized is not implemented for the type Self
,因為我將*self
傳遞給process_trait。 難道我做錯了什么? 我嘗試改變這一點,甚至施法,我得到這個錯誤或錯誤的類型。
我認為問題是它應該是堆分配的,不是嗎? 我唯一要避免的是API看起來很難看。 用戶應該能夠
struct MyUnit;
impl MyTrait for MyUnit...
MyUnit.callC();
按值傳遞特征對象沒有意義,尤其是在與C交互時。實際類型(在C意義上)及其大小未知,並且對象內部沒有vtable。 您最有可能想要傳遞特征參考( &MyTrait
)。 但是,特征對C來說是陌生的,因此會形成一個糟糕的界面。 雖然您可以在C中定義core::raw::TraitObject
的等價物,但實際上對vtable執行任何操作都非常難看且易碎core::raw::TraitObject
安全。
如果您在銹-C屏障需要多態,顯函數指針是一個更好的選擇。 你仍然可以擁有MyTrait
和callC
方法,它只是看起來不同的FFI部分。 可以將C庫回調與對象一起作為有效負載進行處理。
或者,傳遞前面提到的TraitObject
(胖指針)但從不從C檢查它們,通過Rust中的(非特征)輔助函數調用方法:
extern fn call_method(obj: TraitObject) {
let obj: &MyTrait = transmute(obj); // should be safe, but not tested
obj.meth();
}
這避免了手動挖掘C中Rust vtable的麻煩。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.