Macro ffi_helpers::null_pointer_check
[−]
[src]
macro_rules! null_pointer_check { ($ptr:expr) => { ... }; ($ptr:expr, $null:expr) => { ... }; }
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 { 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) { 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 { 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 */ }