未来
RFC 1861 引入了外部类型的概念。在实施时,它还没有稳定下来。一旦实现,它将成为首选实现:
#![feature(extern_types)]
extern "C" {
type Foo;
}
type FooPtr = *mut Foo;
今天
The documentation 状态:
要在 Rust 中做到这一点,让我们创建自己的不透明类型:
#[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);
}
通过包含一个私有字段并且没有构造函数,我们创建了一个不透明的
我们无法在此模块之外实例化的类型。一个空数组
既是零大小又与#[repr(C)] 兼容。但是因为我们的
Foo 和 Bar 类型不同,我们将在
其中两个,所以我们不能不小心将指向Foo 的指针传递给
bar().
创建了一个不透明的指针,因此没有正常的方法来创建这种类型;你只能创建指向它的指针。
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
因此它是一个不透明的指针。移动结构体MyRustType 不会改变指针的值。
过去
此答案的先前迭代和建议使用空枚举 (enum MyTypeFromC {}) 的文档。没有变体的枚举在语义上等同于 never 类型 (!),这是一种不存在的类型。有人担心使用这样的构造可能会导致未定义的行为,因此移动到空数组被认为更安全。