我在Rust中包装一个C库,它的许多函数通过指向结构的指针来获取参数,这些结构本身通常具有指向其他结构的指针 . 为了减少开销,我想提供将Rust数据编组的结果缓存到C结构中的能力 .
以下是C库如何期望某些参数的示例:
#[repr(C)]
struct Foo {
x: i32,
y: f32
}
#[repr(C)]
struct Bar {
p_foo: *const Foo,
z: bool
}
我怎么想象一个拥有的“缓存”版本看起来:
struct Cached {
foo: Option<Foo>,
bar: Bar
}
bar
的 p_foo
字段将被构造为指向 foo
中的 Some
值,或者如果存在 None
则指向空指针 .
当然,问题在于,如果要移动 Cached
的值,则直接 memcpy
将是不合适的,并且还需要重定向 bar.p_foo
. 这很容易用C语言确定,具有可定义的移动语义,但Rust除了提供一个解决方案之外“不设置 bar.p_foo
,直到它想象这些缓存的值将被移动超过(甚至接近频率) )它们被重用,并且有一些工作涉及设置这些指针,特别是如果嵌套/链接很深/很长 . 我也不愿意在堆上的子结构中使用.2860352_ .
为了澄清,这里是我可以用C编写的内容,我想在Rust中复制:
struct Foo {
int x;
float y;
};
struct Bar {
Foo const*pFoo;
bool z;
};
// bear with me while I conjure up a Maybe for C++
class Cached {
public:
// would have appropriate copy constructor/assignment
Cached(Cached &&other) {
m_foo = other.m_foo;
m_bar = other.m_bar;
if(m_foo.isJust()) {
m_bar.pFoo = &m_foo.value();
} // else already nullptr
}
// similar move assignment
private:
Maybe<Foo> m_foo;
Bar m_bar;
};
1 回答
Rust等效的是不使用原始指针,因为原始指针用于实现我们的安全数据结构,而不是用于实现普通数据结构 .
只要
T
是一个类型而不是特征,Option<Box<T>>
保证与*const T
完全等效(在内存中的位) . 唯一的区别是它在Rust中使用是安全的 .这样你甚至不再需要
Cached
结构,但可以直接传递Bar
对象 .然后我建议你不要保留一个
Bar
对象,而是在需要将一个传递给C时召唤它:这听起来很像过早的优化 . 不要优化您没有基准的位置 .