Add Option::as_ptr and Option::as_mut_ptr

When interfacing with C code, I find myself writing repetitive code like this a lot:

p_vertex_input_state: vertex_input_state
    .as_ref()
    .map(|p| p as *const _)
    .unwrap_or(ptr::null()),
p_input_assembly_state: input_assembly_state
    .as_ref()
    .map(|p| p as *const _)
    .unwrap_or(ptr::null()),
p_tessellation_state: tessellation_state
    .as_ref()
    .map(|p| p as *const _)
    .unwrap_or(ptr::null()),
p_viewport_state: viewport_state
    .as_ref()
    .map(|p| p as *const _)
    .unwrap_or(ptr::null()),
p_rasterization_state: rasterization_state
    .as_ref()
    .map(|p| p as *const _)
    .unwrap_or(ptr::null()),
...etc

The p_ members here are all pointers which can be null, while the other variables are Option. Some should be converted to a regular valid pointer, while None should become null. At least in my case this seems like a common enough operation that it might be useful to have two additional methods on Option:

pub fn as_ptr(&self) -> *const T {
    self
        .as_ref()
        .map(|p| p as *const _)
        .unwrap_or(ptr::null())
}

pub fn as_mut_ptr(&mut self) -> *mut T {
    self
        .as_mut()
        .map(|p| p as *mut _)
        .unwrap_or(ptr::null_mut())
}
3 Likes

Can you just define your FFI to take Option<&T>? This is well-defined as nullable:

https://doc.rust-lang.org/std/option/index.html#options-and-pointers-nullable-pointers

The major thing I'd be worried about is confusion between this (&Option<T> -> *const T) and the reffed version (Option<&T> -> *const T).

Given that Option<&_> is the "nullable reference" type (and ABI guaranteed to be a *const T), though, I think it does make sense to provide a way to go Option<&T> -> *const T.

So your original example would be opt.as_ref().as_ptr() instead.

(But also yes, if the FFI expects a pointer that respects Rust's reference rules or NULL, then defining the FFI as taking Option<&T> is best. But sometimes APIs require non-reference-compatible use of pointers, so those need to be defined as *const T.)

2 Likes

In this case the FFI is the Vulkan API, and the Rust bindings I'm using expose these values as pointers.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.