Rust定义指向C opaque指针的字段的成语是什么?

问题描述 投票:1回答:1

给定一个结构:

#[repr(C)]
pub struct User {
    pub name: *const c_char,
    pub age: u8,
    pub ctx: ??,
}

字段ctx只能被C代码操纵;它是指向C struct UserAttr的指针。

根据the Rust FFI documentation,选择将被定义为不透明类型pub enum UserAttr {}。但是,我发现Rust无法复制其值,例如why does the address of an object change across methods

在Rust中定义这样一个不透明指针的正确方法是什么,以便它的值(作为指针)被复制到方法中?

rust
1个回答
6
投票

The future

RFC 1861介绍了外部类型的概念。虽然已经实施,但尚未稳定下来。一旦它,它将成为首选的实现:

#![feature(extern_types)]

extern "C" {
    type Foo;
}

type FooPtr = *mut Foo;

Today

The documentation说:

要在Rust中执行此操作,让我们创建自己的opaque类型:

#[repr(C)] pub struct Foo { private: [u8; 0] }
#[repr(C)] pub struct Bar { private: [u8; 0] }

extern "C" {
    pub fn foo(arg: *mut Foo);
    pub fn bar(arg: *mut Bar);
}

通过包含私有字段而不包含构造函数,我们创建了一个opaque类型,我们无法在此模块之外实例化。空数组既是零大小又与#[repr(C)]兼容。但是因为我们的FooBar类型不同,我们将在它们两者之间获得类型安全,所以我们不会意外地将指针传递给Foobar()

创建一个不透明的指针,这样就没有正常的方法来创建这样的类型;你只能创建它的指针。

mod ffi {
    use std::ptr;

    pub struct MyTypeFromC { _private: [u8; 0] }

    pub fn constructor() -> *mut MyTypeFromC {
        ptr::null_mut()
    }

    pub fn something(_thing: *mut MyTypeFromC) {
        println!("Doing a thing");
    }
}

use ffi::*;

struct MyRustType {
    score: u8,
    the_c_thing: *mut MyTypeFromC,
}

impl MyRustType {
    fn new() -> MyRustType {
        MyRustType {
            score: 42,
            the_c_thing: constructor(),
        }
    }

    fn something(&mut self) {
        println!("My score is {}", self.score);
        ffi::something(self.the_c_thing);
        self.score += 1;
    }
}

fn main() {
    let mut my_thing = MyRustType::new();
    my_thing.something();
}

打破一点:

// opaque -----V~~~~~~~~~V
          *mut MyTypeFromC
//        ^~~^ ------------ pointer

因此它是一个不透明的指针。移动struct MyRustType不会改变指针的值。

The past

此答案的先前迭代和文档建议使用空枚举(enum MyTypeFromC {})。没有变体的枚举在语义上等同于从不类型(!),这是一种不存在的类型。有人担心使用这样的构造可能会导致未定义的行为,因此转移到空阵列被认为更安全。

© www.soinside.com 2019 - 2024. All rights reserved.