Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FFI: Convert nullable pointer to option

Tags:

casting

rust

ffi

I'm using rust-bindgen to access a C library from Rust. Some functions return nullable pointers to structs, which bindgen represents as

extern "C" {
    pub fn get_some_data() -> *const SomeStruct;
}

Now, for a higher level wrapper, I would like to convert this to a Option<&'a SomeStruct> with an appropriate lifetime. Due to the nullable pointer optimization, this is actually represented identically to *const SomeStruct. However, I couln't find any concise syntax to cast between the two. Transmuting

let data: Option<&'a SomeStruct> = unsafe { mem::transmute( get_some_data() ) };

and reborrowing

let data_ptr = get_some_data();
let data = if data_ptr.is_null() { None } else { unsafe { &*data_ptr } };

could be used. The docs for mem::transmute state that

transmute is incredibly unsafe. There are a vast number of ways to cause undefined behavior with this function. transmute should be the absolute last resort.

and recommends re-borrowing instead for

Turning a *mut T into an &mut T

However, for the nullable pointer, this is quite clumsy as shown in the second example.

Q: Is there a more concise Syntax for this cast? Alternatively, is there a way to tell bindgen to generate

extern "C" {
    pub fn get_some_data() -> Option<&SomeStruct>;
}

directly?

like image 809
Wisperwind Avatar asked May 05 '26 22:05

Wisperwind


1 Answers

Use <*const T>::as_ref¹:

let data = unsafe { get_some_data().as_ref() };

Since a raw pointer may not point to a valid object of sufficient lifetime for any 'a, as_ref is unsafe to call.

There is a corresponding as_mut for *mut TOption<&mut T>.


¹ This is a different as_ref from, for example, AsRef::as_ref and Option::as_ref, both of which are common in safe code.

like image 100
trent Avatar answered May 08 '26 17:05

trent