How to check if function pointer passed from C is non-NULL

余生长醉 提交于 2019-12-07 02:10:17

问题


Example code below

The Rust part:

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

And the C part:

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;
}

Of course second call of call_c_function will crash. Rust compiler will not complain about unsafe code inside call_c_function, because from rust point of view this code is safe. Also it's not allowed to simply write:

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

because fun type is fn(i32) -> i32 (it's not a pointer).

So my question is, how I can protect call_c_function against NULL pointer dereference? Is there any way to check if callback passed from C is not valid?

Maybe I have to change call_c_function definition?


回答1:


You can use Option<...> to represent nullable function pointers. It is incorrect to have a NULL value for a value of type fn(...) so the Option wrapper is required for cases like this.

For example,

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

However, there's on extra point: fun is a C function, but the type fn(...) is a Rust function. They're not directly compatible (e.g. their calling conventions differ), one needs to be using the extern "C" fn(...) (aka extern fn(...)) type when interacting with C function pointers:

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


来源:https://stackoverflow.com/questions/31481102/how-to-check-if-function-pointer-passed-from-c-is-non-null

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!