Macro ffi_helpers::null_pointer_check[][src]

macro_rules! null_pointer_check {
    ($ptr : expr) => { ... };
    ($ptr : expr, $null : expr) => { ... };
}
Expand description

Check if we’ve been given a null pointer, if so we’ll return early.

The returned value is the NULL value for whatever type the calling function returns. The LAST_ERROR thread-local variable is also updated with NullPointer.

Examples

The typical use case is to call null_pointer_check!() before doing an operation with a raw pointer. For example, say a C function passes you a pointer to some Rust object so it can get a reference to something inside:

struct Foo {
  data: Vec<u8>,
}

#[no_mangle]
unsafe extern "C" fn foo_get_data(foo: *const Foo) -> *const u8 {
    ffi_helpers::null_pointer_check!(foo);

    let foo = &*foo;
    foo.data.as_ptr()
}

Because Nullable is implemented for () you can also use the macro as a cheap way to return early from a function. As an example, destructors are a common place where you don’t want to do anything if passed a NULL pointer.

struct Foo {
  data: Vec<u8>,
}

#[no_mangle]
unsafe extern "C" fn foo_destroy(foo: *mut Foo) {
    ffi_helpers::null_pointer_check!(foo);

    let foo = Box::from_raw(foo);
    drop(foo);
}

Sometimes when there’s an error you’ll use something different. For example when writing data into a buffer you’ll usually return the number of bytes written. Because 0 (the NULL value for an integer) is typically a valid number of bytes, you’ll return -1 to indicate there was an error.

The null_pointer_check!() macro accepts a second argument to allow this.

use libc::{c_char, c_int};
use std::slice;

#[no_mangle]
unsafe extern "C" fn write_message(buf: *mut c_char, length: c_int) -> c_int {
    ffi_helpers::null_pointer_check!(buf, -1);
    let mut buffer = slice::from_raw_parts_mut(buf as *mut u8, length as usize);

    /* write some data into the buffer */
}