如何检查从C传递的函数指针是否为非空

如何检查从C传递的函数指针是否为非空,c,rust,ffi,C,Rust,Ffi,下面是示例代码 生锈部分: #[no_mangle] pub extern fn call_c_function(value: i32, fun: fn(i32) -> i32) -> i32 { fun(value) } C部分: int32_t call_c_function(int32_t value, int32_t (*fun)(int32_t)); int32_t triple(int32_t x) { return x*3; } int main(

下面是示例代码

生锈部分:

#[no_mangle]
pub extern fn call_c_function(value: i32, fun: fn(i32) -> i32) -> i32 {
    fun(value)
}
C部分:

int32_t call_c_function(int32_t value, int32_t (*fun)(int32_t));

int32_t triple(int32_t x)
{
    return x*3;
}

int main(int argc, char *argv[])
{
    int32_t value = 3;
    int32_t result = call_c_function(value, triple);

    printf("%d tripled is %d\n", value, result);

    call_c_function(0, NULL);  // Crash here

    return EXIT_SUCCESS;
}
当然,
call\u c\u函数的第二次调用将崩溃。
Rust编译器不会抱怨调用c_函数中的不安全代码,因为从Rust的角度来看,这段代码是安全的。此外,不允许简单地写:

if !fun.is_null() {
    fun(value)
}
因为
fun
类型是
fn(i32)->i32
(它不是指针)

所以我的问题是,我如何保护
调用c_函数
不受空指针解引用的影响?有没有办法检查从C传递的回调是否无效

也许我必须更改
调用函数
定义?

您可以使用
选项
表示可为空的函数指针。对于类型为
fn(…)
的值,使用空值是不正确的,因此对于此类情况,需要使用
选项
包装器

比如说,

#[no_mangle]
pub extern "C" fn call_c_function(value: i32, fun: Option<fn(i32) -> i32>) -> i32 {
    if let Some(f) = fun {
        f(value)
    }
}

您可以将不安全代码生成的指针与
std::ptr::null()

e、 g


null()
在Linux上是
0 as*const T
我不确定这是否通用。

是的,只需检查fun==null。或者零,如果NULL不是生锈的东西。请注意,我不太了解rust,但在C中就是这样。请看这里:@Adrian Thx,这就是我要找的!这不适用于函数指针,正如huon的回答所解释的,函数指针是不可为空的。
#[no_mangle]
pub extern "C" fn call_c_function(value: i32, fun: Option<extern "C" fn(i32) -> i32>) -> i32 {
    if let Some(f) = fun {
        f(value)
    }
}
let pw = libc::getpwnam(username.as_ptr() as *const i8);
if std::ptr::null() != pw ...