如何检查从 C 传递的函数指针是否为非 NULL
How to check if function pointer passed from C is non-NULL
下面的示例代码
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 函数。它们不直接兼容(例如,它们的调用约定不同)。与 C 函数指针交互时需要使用 extern "C" fn(...)
(a.k.a. extern fn(...)
) 类型:
#[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)
}
}
您可以将不安全代码生成的指针与 std::ptr::null()
进行比较
例如
let pw = libc::getpwnam(username.as_ptr() as *const i8);
if std::ptr::null() != pw ...
null()
在 Linux 上是 0 as *const T
我不确定这是否通用。
下面的示例代码
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 函数。它们不直接兼容(例如,它们的调用约定不同)。与 C 函数指针交互时需要使用 extern "C" fn(...)
(a.k.a. extern fn(...)
) 类型:
#[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)
}
}
您可以将不安全代码生成的指针与 std::ptr::null()
例如
let pw = libc::getpwnam(username.as_ptr() as *const i8);
if std::ptr::null() != pw ...
null()
在 Linux 上是 0 as *const T
我不确定这是否通用。