我想在C++类中包装一个Rust结构.
锈:
#[repr(C)]
pub struct RustStruct {
num: i32,
// other members..
}
pub extern "C" fn update(rust_struct: *mut RustStruct) {
(*rust_struct).num = 1i32;
}
extern "C" {
void update(void*);
}
Run Code Online (Sandbox Code Playgroud)
C++:
class Wrapper {
public:
Wrapper();
// ..
private:
void* rustStruct;
// ..
};
Wrapper::Wrapper() {
update(rustStruct); // crash
}
int main() {
std::cout << "Testing..";
}
Run Code Online (Sandbox Code Playgroud)
我理解为什么这不起作用.我的问题是:我怎样才能实现我基本上要做的事情(在c ++类中包装一个rust结构)?
Mat*_* M. 10
您的答案中有多个FFI概念的混合,所以首先让我建议您阅读参考.
有两种方法可以达到你想要的效果,你可以:
struct(普通旧数据),又称C兼容结构void*在C中)像你一样混合它们是没有意义的.
选哪个?
这两种解决方案都有优点和缺点,它基本上是表达性与性能权衡.
一方面,不透明指针更具表现力:它们可以指向任何Rust类型.然而:
另一方面,POD结构不需要其中任何一个,但它们仅限于Rust中可表达的类型的子集.
如何使用POD?
实际上,这是最简单的,所以让我们从它开始吧!
在Rust:
#[repr(C)]
pub struct RustStruct {
num: i32,
// other members, also PODs!
}
Run Code Online (Sandbox Code Playgroud)
在C++中
struct RustStruct {
int32_t num;
// other members, also with Standard Layout
// http://en.cppreference.com/w/cpp/types/is_standard_layout
};
class Wrapper {
public:
private:
RustStruct rustStruct;
};
Run Code Online (Sandbox Code Playgroud)
请注意,我刚刚在这里提出了你的问题stricto censu,你实际上可以在一个C++类中合并这两个:
class RustStruct {
public:
private:
int32_t num;
// other members, also with Standard Layout
// http://en.cppreference.com/w/cpp/types/is_standard_layout
};
Run Code Online (Sandbox Code Playgroud)
只是避免virtual方法.
如何使用不透明指针?
这变得更棘手:
所以,我们需要在Rust中实现很多功能:
#![feature(box_raw, box_syntax)]
use std::boxed;
pub struct RustStruct {
num: i32,
// other members, anything goes
}
pub extern "C" fn createRustStruct() -> *mut RustStruct {
boxed::into_raw(box RustStruct::new())
}
pub extern "C" fn destroyRustStruct(o: *mut RustStruct) {
boxed::from_raw(o);
}
Run Code Online (Sandbox Code Playgroud)
好吧......现在开始使用C++:
struct RustStruct;
RustStruct* createRustStruct();
void destroyRustStruct(RustStruct*);
class Wrapper {
public:
Wrapper(): rustStruct(RustStructPtr(createRustStruct())) {}
private:
struct Deleter {
void operator()(RustStruct* rs) const {
destroyRustStruct(rs);
}
};
typedef std::unique_ptr<RustStruct, Deleter> RustStructPtr;
RustStructPtr rustStruct;
}; // class Wrapper
Run Code Online (Sandbox Code Playgroud)
所以,是的,更多涉及,并且Wrapper也不可复制(复制也必须委托给Rust).无论如何,这应该让你开始!
注意:如果你有很多不透明的指针需要包装,那么将复制/销毁函数作为模板参数的模板化C++类可以减轻很多锅炉板块.