如何将特征对象的一部分传递给 C
How to pass a slice of trait objects to C
我最近一直在开发一个库,我想为它制作 C 绑定。该库中的一个结构 returns 用户的特征对象片段。这是函数定义的样子:
pub fn controllers(&self) -> &[Box<dyn Controller>] {
&self.controllers
}
我不确定如何翻译这个。 C 代码将 而不是 插入这些动态对象中。它只会将它们传递回 Rust 代码,即
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;并且您似乎想将它们作为 (pointer, length) 对传递给 C,以便 C 可以迭代它们。然而,这意味着 C 需要知道每个特征对象有多大(比单个指针大;共享切片也是如此)。
相反,我会为集合和相关函数提供一个不透明的句柄以对其进行迭代。只有当性能非常重要时,我才会让 C 知道每个元素的大小(这意味着 ABI 将取决于 Rust 如何表示 DST)。
有关技术细节,请查看 等问题。
我最近一直在开发一个库,我想为它制作 C 绑定。该库中的一个结构 returns 用户的特征对象片段。这是函数定义的样子:
pub fn controllers(&self) -> &[Box<dyn Controller>] {
&self.controllers
}
我不确定如何翻译这个。 C 代码将 而不是 插入这些动态对象中。它只会将它们传递回 Rust 代码,即
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;并且您似乎想将它们作为 (pointer, length) 对传递给 C,以便 C 可以迭代它们。然而,这意味着 C 需要知道每个特征对象有多大(比单个指针大;共享切片也是如此)。
相反,我会为集合和相关函数提供一个不透明的句柄以对其进行迭代。只有当性能非常重要时,我才会让 C 知道每个元素的大小(这意味着 ABI 将取决于 Rust 如何表示 DST)。
有关技术细节,请查看