rust - 如何将一片特征对象传递给C
问题描述
我最近一直在研究一个库,我想为它做 C 绑定。这个库中的一个结构体向用户返回了一个特征对象的片段。这是函数定义的样子:
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
返回的是 a*const Box<dyn Controller>
而不是*const dyn Controller
. 我可以在这里做什么?
解决方案
在编写 C 绑定时,应该从 C 端考虑,要提供哪些操作,尽可能隐藏实现。
例如,您说 C 代码将使用 trait 对象回调 Rust;并且您似乎想将它们作为(指针,长度)对传递给 C,以便 C 可以迭代它们。然而,这意味着 C 需要知道每个特征对象有多大(比单个指针大;对于共享切片也是如此)。
相反,我会为集合和关联函数提供一个不透明的句柄来迭代它。只有当性能非常重要时,我才会让 C 知道每个元素的大小(这意味着 ABI 将取决于 Rust 如何表示 DST)。
有关技术细节,请查看诸如Rust 中的“胖指针”是什么?.
推荐阅读
- node.js - 调用索引时未定义回调
- mongodb - 填充和选择多个子文档 mongoose
- flask - Flask 多线程使用 db 连接
- css - 有条件地将 css 应用于 mat 表单字段
- vscode-settings - 每行左侧的vscode宽度
- python - 以“1992 年 11 月 4 日 (27)”的格式拆分 pandas DataFrame 的 DoB 列,以获得作为日期时间的 DoB
- r - 我尝试创建一个新列,将一列分成两列,然后使用 transmute 函数更改新列,但是 r 抛出错误
- php - ErrorException 不应静态调用非静态方法 - 当尝试从两个不同的表中获取数据时
- android - fastboot 命令超时但设备可见
- python - /pembayaran/ ModelForm 处的 ValueError 未指定模型类