vectores tipos punteros puntero matrices lenguaje funciones declaracion con aritmetica c rust ffi

tipos - punteros y vectores en c



Cómo comprobar si el puntero de función pasado de C no es NULL (1)

Ejemplo de código a continuación

La parte de óxido:

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

Y la parte 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; }

Por supuesto, la segunda llamada de call_c_function se bloqueará. El compilador de oxidación no se quejará sobre el código inseguro dentro de call_c_function , porque desde el punto de vista de oxidación este código es seguro. Además, no está permitido simplemente escribir:

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

porque el tipo de fun es fn(i32) -> i32 (no es un puntero).

Entonces mi pregunta es, ¿cómo puedo proteger call_c_function contra NULL puntero dereference? ¿Hay alguna manera de verificar si la devolución de llamada pasada desde C no es válida?

Tal vez tengo que cambiar la definición call_c_function ?


Puede usar la Option<...> para representar punteros de funciones que aceptan nulos. Es incorrecto tener un valor NULL para un valor de tipo fn(...) por lo que se requiere el contenedor de Option para casos como este.

Por ejemplo,

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

Sin embargo, hay un punto extra: la fun es una función C, pero el tipo fn(...) es una función Rust. No son directamente compatibles (por ejemplo, sus convenciones de llamadas son diferentes), uno necesita usar el tipo extern "C" fn(...) (aka extern fn(...) ) al interactuar con los punteros de función C:

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