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

标签 c rust ffi

下面的示例代码

Rust 部分:

#[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_c_function 会崩溃。 Rust 编译器不会提示 call_c_function 中的不安全代码,因为从 Rust 的角度来看,这段代码是安全的。也不允许简单地写:

if !fun.is_null() {
    fun(value)
}

因为 fun 类型是 fn(i32) -> i32(它不是指针)。

所以我的问题是,如何保护 call_c_function 免受 NULL 指针取消引用?有什么方法可以检查从 C 传递的回调是否无效?

也许我必须更改 call_c_function 定义?

最佳答案

您可以使用 Option<...>表示可为空的函数指针。 fn(...) 类型的值具有 NULL 值是不正确的所以 Option这种情况需要包装器。

例如,

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

但是,还有一点:fun是一个 C 函数,但是类型 fn(...)是一个 Rust 函数。它们不直接兼容(例如,它们的调用约定不同)。需要使用 extern "C" fn(...) (又名 extern fn(...) )与 C 函数指针交互时的类型:

#[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)
    }
}

关于c - 如何检查从 C 传递的函数指针是否为非 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31481102/

相关文章:

c++ - 分配内存并调用 C++ 回调的 Rust 函数崩溃

rust - 对闭包中 ref 关键字的使用感到困惑

rust - 为什么可以在 String 上调用 Colorize trait 方法,而 String 不实现 Colorize

lua - LuaJIT 的 FFI 可以像 JIT 那样被禁用吗?

通过递归下降解析创建 cons cell 结构

macros - 我找不到 `mock!` 的定义

c - 编译 C 程序时无法链接到 Rust 编译的库

c - 多次 Recv 调用 Socket C 编程

c - C中的旋转程序

c - Gnu Scientific Library 的曲线拟合示例代码无法运行。