使用Rust FFI时如何初始化不透明的C结构? [英] How do I initialize an opaque C struct when using Rust FFI?

查看:201
本文介绍了使用Rust FFI时如何初始化不透明的C结构?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这就是我想用C代码做的事情:

Here's what I would like to do in C code:

#include <some_lib.h>
int main() {
    some_lib_struct_t x;
    some_lib_func(&x);
}

如何使用Rust中的库?这是到目前为止我得到的:

How do I make use of the library in Rust? Here's what I've got so far:

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);
    }
}

编译时出现错误:

error[E0381]: borrow of possibly uninitialized variable: `x`
  --> src/main.rs:13:23
   |
13 |         some_lib_func(&mut x);
   |                       ^^^^^^ use of possibly uninitialized `x`

推荐答案

最安全的答案是自己初始化结构:

The safest answer is to initialize the struct yourself:

let mut x: some_lib_struct_t = some_lib_struct_t;
unsafe {
    some_lib_func(&mut x);
}

与C代码最接近的类似物是使用 MaybeUninit

The closest analog to the C code is to use MaybeUninit

use std::mem::MaybeUninit;

unsafe {
    let mut x = MaybeUninit::uninit();
    some_lib_func(x.as_mut_ptr());
}

在Rust 1.36之前,您可以使用 mem::uninitialized :

Before Rust 1.36, you can use mem::uninitialized:

unsafe {
    let mut x: some_lib_struct_t = std::mem::uninitialized();
    some_lib_func(&mut x);
}

必须确保some_lib_func完全初始化了该结构的所有成员,否则不安全性将泄漏到unsafe块之外.

You have to be sure that some_lib_func completely initializes all the members of the struct, otherwise the unsafety will leak outside of the unsafe block.

说到结构成员",我几乎可以保证您的代码不会做您想要的事情.您已将some_lib_struct_t定义为零大小.这意味着不会为其分配堆栈空间,并且对它的引用将不是您的C代码所期望的.

Speaking of "members of the struct", I can almost guarantee your code won't do what you want. You've defined some_lib_struct_t as having zero size. That means that no stack space will be allocated for it, and a reference to it won't be what your C code is expecting.

您需要镜像Rust中C结构的定义,以便可以分配适当的大小,填充和对齐方式.通常,这意味着使用repr(C).

You need to mirror the definition of the C struct in Rust so that the appropriate size, padding, and alignment can be allocated. Usually, this means using repr(C).

很多时候,C库总是通过返回不透明类型的指针来避免暴露其内部结构表示形式:

Many times, C libraries avoid exposing their internal struct representation by always returning a pointer to the opaque type:

  • What's the Rust idiom to define a field pointing to a C opaque pointer?
  • In Rust how can I define or import a C struct from a third party library?
  • Allocating an object for C / FFI library calls

这篇关于使用Rust FFI时如何初始化不透明的C结构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆