我有这个C代码:
typedef void (*f_t)(int a);
struct Foo {
f_t f;
};
extern void f(struct Foo *);
Run Code Online (Sandbox Code Playgroud)
bindgen生成以下Rust代码(我删除了不重要的细节):
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct Foo {
pub f: ::std::option::Option<extern "C" fn(a: ::std::os::raw::c_int)>,
}
Run Code Online (Sandbox Code Playgroud)
我不明白为什么Option在这里.显然Rust enum和C指针在位级别上是不一样的,所以Rust编译器如何处理这个?
当我调用C f函数并将指针传递给Rust结构时Foo,编译器是否转换Foo_rust为Foo_C然后仅将指针传递Foo_C给f?
来自关于FFI的Rust编程语言章节(强调我的):
某些类型被定义为不为null.这包括引用(
&T,&mut T),方框(Box<T>)和函数指针(extern "abi" fn()).当与C接口时,经常使用可能为null的指针.作为一种特殊情况,包含两个变体的通用枚举,其中一个不包含数据,另一个包含单个字段,符合"可空指针优化"的条件.当用非可空类型之一实例化这样的枚举时,它被表示为单个指针,并且非数据变量被表示为空指针.那么Option<extern "C" fn(c_int) -> c_int>如何使用C ABI表示可空函数指针.
换句话说:
显然,Rust枚举和C指针在位级别上并不相同
实际上,它们Option包含一组特定的类型.
也可以看看: