最合适的类型为不透明的外部静态在Rust?



我想获得一个指向ffi定义的静态对象的原始指针,该对象的具体类型对于Rust是不透明的。

这是我目前拥有的:

use std::{ffi::c_void, ptr::addr_of};
fn ptr_to_foo() -> *const c_void {
extern "C" {
static FOO: /* what type here? */;
}
unsafe { addr_of!(FOO).cast() }
}

但是应该用什么类型声明FOO呢?

是UB声明它c_void,考虑到内存位置的字节可能对该类型无效-即使我只创建一个指向该位置的原始指针而没有构造引用(或者更糟,解引用指针/读取内存)?

如果是这样,还有什么比u8更合适的方法吗?或者它(或它周围的新类型)会是推荐的方法吗?

如果是夜间使用,则使用外部类型。它们是一种仅限夜间使用的方法,用于创建编译器知道在任何情况下都不能解引用的动态大小类型,并且是专门为ffi使用而设计的。

#![feature(extern_types)]
extern "C"{
type Foo;
static FOO: Foo;
}

游乐场

另一种选择是使用带有私有字段且没有公共构造函数的零大小类型:

#[repr(C)]
struct Foo{
_inner: [u8;0]
}
extern "C"{
static FOO: Foo;
}

游乐场

如果您使用的指针非空、对齐良好且不指向已释放的内存,则ZST读写总是有效的,因此尽管您仍然可以从静态中读取,但这样做是定义良好的。唯一需要注意的是,如果将返回的指针转换为可变引用,将导致未定义的行为,但这是静态的问题,而不是类型的问题。

最新更新