我正在构建一个 Rust 库,需要使用 Rust 对象调用一些 C 函数。我有一个调用 C 函数的函数的特征,C 函数在 Rust 中定义如下:
extern {
fn process_trait(my_trait: MyTrait);
}
这个想法是,用户可以为其结构实现特征,然后调用 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 来说是陌生的,因此会产生糟糕的接口。虽然您可以定义相当于core::raw::TraitObject
在 C 语言中,实际上用 vtable 做任何事情都是极其丑陋、脆弱和不安全的。
如果您需要跨 Rust-C 屏障的多态性,显式函数指针是一个不错的选择much更好的选择。你仍然可以拥有MyTrait
和callC
方法,只是 FFI 部分看起来不同。可以将对象作为有效负载传递给 C 库回调。
或者,绕过上述TraitObject
s(胖指针),但永远不要从 C 中检查它们,通过 Rust 中的(非特征)辅助函数调用方法:
extern fn call_method(obj: TraitObject) {
let obj: &MyTrait = transmute(obj); // should be safe, but not tested
obj.meth();
}
这避免了在 C 中手动挖掘 Rust vtable 的麻烦。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)