如何将特征对象的切片传递给C

  • 本文关键字:切片 特征 对象 rust ffi
  • 更新时间 :
  • 英文 :


我最近一直在开发一个库,我想为它制作C绑定。这个库中的一个structs向用户返回一片trait对象。这就是函数定义的样子:

pub fn controllers(&self) -> &[Box<dyn Controller>] {
&self.controllers
}

我不知道如何翻译这个。C代码将而不是插入这些动态对象。它将简单地将它们传递回铁锈代码,即

pub fn controller_get_name(controller: *const dyn Controller) -> *const c_char {
let controller = controller.as_ref();
controller.get_name().as_ptr();
}

目前,我有这个:

#[no_mangle]
pub extern "C" fn libvibrant_instance_get_controllers(instance: *mut Instance,
mut controllers: *const dyn Controller,
len: *mut usize) {
assert!(!instance.is_null());
assert!(!len.is_null());
let instance = unsafe { instance.as_ref().unwrap() };
controllers = instance.controllers().as_ptr();
unsafe {
*len = instance.controllers().len();
}
}

但显然,这不起作用,因为as_ptr返回的是*const Box<dyn Controller>而不是*const dyn Controller。我在这里能做什么?

在编写C绑定时,您应该从C端考虑,以及您想要提供什么操作,尽可能隐藏实现。

例如,您说C代码将使用trait对象回调Rust;看起来你想把它们作为(指针,长度(对传递给C,这样C就可以对它们进行迭代。然而,这意味着C需要知道每个特征对象有多大(比单个指针大;共享切片也是如此(。

相反,我会为集合和相关函数提供一个不透明的句柄来迭代它。只有当性能非常重要时,我才会让C知道每个元素的大小(这意味着ABI将取决于Rust如何表示DST(。

有关技术细节,请查看诸如Rust中的"胖指针"是什么之类的问题?。

最新更新