我想获得一个指向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读写总是有效的,因此尽管您仍然可以从静态中读取,但这样做是定义良好的。唯一需要注意的是,如果将返回的指针转换为可变引用,将导致未定义的行为,但这是静态的问题,而不是类型的问题。