使用Rust FFI时,如何初始化不透明的C结构?
下面是我在C代码中要做的事情:使用Rust FFI时,如何初始化不透明的C结构?,rust,ffi,Rust,Ffi,下面是我在C代码中要做的事情: #包括 int main(){ 一些库结构; 一些_lib_func(&x); } 我如何利用图书馆?以下是到目前为止我得到的信息: extern crate libc; // 0.2.51 struct some_lib_struct_t; #[link(name = "some_lib")] extern "C" { fn some_lib_func(x: *mut some_lib_struct_t); } fn main() { l
#包括
int main(){
一些库结构;
一些_lib_func(&x);
}
我如何利用图书馆?以下是到目前为止我得到的信息:
extern crate libc; // 0.2.51
struct some_lib_struct_t;
#[link(name = "some_lib")]
extern "C" {
fn some_lib_func(x: *mut some_lib_struct_t);
}
fn main() {
let mut x: some_lib_struct_t;
unsafe {
some_lib_func(&mut x);
}
}
编译时出现错误:
错误[E0381]:借用可能未初始化的变量:`x`
-->src/main.rs:13:23
|
13 |一些自由函数(&mut x);
|^^^^^^使用可能未初始化的`x`
最安全的答案是自己初始化结构:
let mut x: some_lib_struct_t = some_lib_struct_t;
unsafe {
some_lib_func(&mut x);
}
与C代码最接近的模拟是使用
在生锈1.36之前,您可以使用:
必须确保某些_lib_func
完全初始化结构的所有成员,否则不安全性将泄漏到不安全
块之外
说到“结构的成员”,我几乎可以保证你的代码不会做你想做的事情。您已将某些库结构定义为大小为零。这意味着不会为它分配堆栈空间,对它的引用也不会是您的C代码所期望的
您需要在Rust中镜像C结构的定义,以便可以分配适当的大小、填充和对齐方式。通常,这意味着使用repr(C)
很多时候,C库总是返回指向不透明类型的指针,从而避免暴露其内部结构表示:
阅读后,我仔细查看了库的标题。正如他们所说,some_lib_struct
只是指向real_lib_struct
的指针的类型定义。我做了以下修改:
extern crate libc;
struct actual_lib_struct_t;
type some_lib_type_t = *mut actual_lib_struct_t;
#[link(name="some_lib")]
extern {
fn some_lib_func(x: *mut some_lib_type_t);
}
fn main() {
let mut x: some_lib_type_t;
unsafe {
x = std::mem::uninitialized();
some_lib_func(&mut x);
}
}
而且它有效!然而,我确实得到了警告:代码>在外部模块中找到了零大小结构,考虑将一个成员添加到这个结构中,{ [警告(不正确的cType)]默认为 .< /P> < p>从文档中获得:
自1.39.0以来已弃用:改用
新的解决方案如下所示:
使用std::mem::maybeunit;
让实例=不安全{
设mut x:maybeunit=maybeunit::uninit();
一些函数(x.as_mut_ptr());
x、 假设_init()
}
我使用mem::uninitialized()实现了它。但是我从编译器那里得到一个警告。我用更多信息更新了这个问题。@EFTH我已经解决了这个问题。请参阅我的答案中有关“零尺寸”的部分。如果您有一个不透明的指针,那么请查看3个链接问题。请注意,自1.39.0以来,std::mem::uninitialized
已被弃用:请改用mem::maybeuniit
。
unsafe {
let mut x: some_lib_struct_t = std::mem::uninitialized();
some_lib_func(&mut x);
}
extern crate libc;
struct actual_lib_struct_t;
type some_lib_type_t = *mut actual_lib_struct_t;
#[link(name="some_lib")]
extern {
fn some_lib_func(x: *mut some_lib_type_t);
}
fn main() {
let mut x: some_lib_type_t;
unsafe {
x = std::mem::uninitialized();
some_lib_func(&mut x);
}
}