diff --git a/crates/servicepoint_binding_c/src/bit_vec.rs b/crates/servicepoint_binding_c/src/bit_vec.rs index d1b353c..8b9e94f 100644 --- a/crates/servicepoint_binding_c/src/bit_vec.rs +++ b/crates/servicepoint_binding_c/src/bit_vec.rs @@ -1,4 +1,4 @@ -//! C functions for interacting with `SPBitVec`s +//! C functions for interacting with [SPBitVec]s //! //! prefix `sp_bit_vec_` @@ -33,17 +33,17 @@ impl Clone for SPBitVec { } } -/// Creates a new `SPBitVec` instance. +/// Creates a new [SPBitVec] instance. /// /// # Arguments /// /// - `size`: size in bits. /// -/// returns: `SPBitVec` with all bits set to false. Will never return NULL. +/// returns: [SPBitVec] with all bits set to false. Will never return NULL. /// /// # Panics /// -/// When `size` is not divisible by 8. +/// - when `size` is not divisible by 8. /// /// # Safety /// @@ -53,10 +53,18 @@ impl Clone for SPBitVec { /// by explicitly calling `sp_bit_vec_free`. #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_new(size: usize) -> *mut SPBitVec { - Box::into_raw(Box::new(SPBitVec(BitVec::repeat(false, size)))) + let result = Box::into_raw(Box::new(SPBitVec(BitVec::repeat(false, size)))); + assert!(!result.is_null()); + result } -/// Interpret the data as a series of bits and load then into a new `SPBitVec` instance. +/// Interpret the data as a series of bits and load then into a new [SPBitVec] instance. +/// +/// returns: [SPBitVec] instance containing data. Will never return NULL. +/// +/// # Panics +/// +/// - when `data` is NULL /// /// # Safety /// @@ -71,17 +79,26 @@ pub unsafe extern "C" fn sp_bit_vec_load( data: *const u8, data_length: usize, ) -> *mut SPBitVec { + assert!(!data.is_null()); let data = std::slice::from_raw_parts(data, data_length); - Box::into_raw(Box::new(SPBitVec(BitVec::from_slice(data)))) + let result = Box::into_raw(Box::new(SPBitVec(BitVec::from_slice(data)))); + assert!(!result.is_null()); + result } -/// Clones a `SPBitVec`. +/// Clones a [SPBitVec]. +/// +/// returns: new [SPBitVec] instance. Will never return NULL. +/// +/// # Panics +/// +/// - when `bit_vec` is NULL /// /// # Safety /// /// The caller has to make sure that: /// -/// - `bit_vec` points to a valid `SPBitVec` +/// - `bit_vec` points to a valid [SPBitVec] /// - `bit_vec` is not written to concurrently /// - the returned instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_bit_vec_free`. @@ -89,24 +106,32 @@ pub unsafe extern "C" fn sp_bit_vec_load( pub unsafe extern "C" fn sp_bit_vec_clone( bit_vec: *const SPBitVec, ) -> *mut SPBitVec { - Box::into_raw(Box::new((*bit_vec).clone())) + assert!(!bit_vec.is_null()); + let result = Box::into_raw(Box::new((*bit_vec).clone())); + assert!(!result.is_null()); + result } -/// Deallocates a `SPBitVec`. +/// Deallocates a [SPBitVec]. +/// +/// # Panics +/// +/// - when `but_vec` is NULL /// /// # Safety /// /// The caller has to make sure that: /// -/// - `bit_vec` points to a valid `SPBitVec` +/// - `bit_vec` points to a valid [SPBitVec] /// - `bit_vec` is not used concurrently or after this call -/// - `bit_vec` was not passed to another consuming function, e.g. to create a `SPCommand` +/// - `bit_vec` was not passed to another consuming function, e.g. to create a [SPCommand] #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_free(bit_vec: *mut SPBitVec) { + assert!(!bit_vec.is_null()); _ = Box::from_raw(bit_vec); } -/// Gets the value of a bit from the `SPBitVec`. +/// Gets the value of a bit from the [SPBitVec]. /// /// # Arguments /// @@ -117,23 +142,25 @@ pub unsafe extern "C" fn sp_bit_vec_free(bit_vec: *mut SPBitVec) { /// /// # Panics /// -/// When accessing `index` out of bounds. +/// - when `bit_vec` is NULL +/// - when accessing `index` out of bounds /// /// # Safety /// /// The caller has to make sure that: /// -/// - `bit_vec` points to a valid `SPBitVec` +/// - `bit_vec` points to a valid [SPBitVec] /// - `bit_vec` is not written to concurrently #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_get( bit_vec: *const SPBitVec, index: usize, ) -> bool { + assert!(!bit_vec.is_null()); *(*bit_vec).0.get(index).unwrap() } -/// Sets the value of a bit in the `SPBitVec`. +/// Sets the value of a bit in the [SPBitVec]. /// /// # Arguments /// @@ -141,17 +168,16 @@ pub unsafe extern "C" fn sp_bit_vec_get( /// - `index`: the bit index to edit /// - `value`: the value to set the bit to /// -/// returns: old value of the bit -/// /// # Panics /// -/// When accessing `index` out of bounds. +/// - when `bit_vec` is NULL +/// - when accessing `index` out of bounds /// /// # Safety /// /// The caller has to make sure that: /// -/// - `bit_vec` points to a valid `SPBitVec` +/// - `bit_vec` points to a valid [SPBitVec] /// - `bit_vec` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_set( @@ -159,40 +185,51 @@ pub unsafe extern "C" fn sp_bit_vec_set( index: usize, value: bool, ) { + assert!(!bit_vec.is_null()); (*bit_vec).0.set(index, value) } -/// Sets the value of all bits in the `SPBitVec`. +/// Sets the value of all bits in the [SPBitVec]. /// /// # Arguments /// /// - `bit_vec`: instance to write to /// - `value`: the value to set all bits to /// +/// # Panics +/// +/// - when `bit_vec` is NULL +/// /// # Safety /// /// The caller has to make sure that: /// -/// - `bit_vec` points to a valid `SPBitVec` +/// - `bit_vec` points to a valid [SPBitVec] /// - `bit_vec` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_fill(bit_vec: *mut SPBitVec, value: bool) { + assert!(!bit_vec.is_null()); (*bit_vec).0.fill(value) } -/// Gets the length of the `SPBitVec` in bits. +/// Gets the length of the [SPBitVec] in bits. /// /// # Arguments /// /// - `bit_vec`: instance to write to /// +/// # Panics +/// +/// - when `bit_vec` is NULL +/// /// # Safety /// /// The caller has to make sure that: /// -/// - `bit_vec` points to a valid `SPBitVec` +/// - `bit_vec` points to a valid [SPBitVec] #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_len(bit_vec: *const SPBitVec) -> usize { + assert!(!bit_vec.is_null()); (*bit_vec).0.len() } @@ -202,33 +239,43 @@ pub unsafe extern "C" fn sp_bit_vec_len(bit_vec: *const SPBitVec) -> usize { /// /// - `bit_vec`: instance to write to /// +/// # Panics +/// +/// - when `bit_vec` is NULL +/// /// # Safety /// /// The caller has to make sure that: /// -/// - `bit_vec` points to a valid `SPBitVec` +/// - `bit_vec` points to a valid [SPBitVec] #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_is_empty(bit_vec: *const SPBitVec) -> bool { + assert!(!bit_vec.is_null()); (*bit_vec).0.is_empty() } -/// Gets an unsafe reference to the data of the `SPBitVec` instance. +/// Gets an unsafe reference to the data of the [SPBitVec] instance. /// /// # Arguments /// /// - `bit_vec`: instance to write to /// +/// # Panics +/// +/// - when `bit_vec` is NULL +/// /// ## Safety /// /// The caller has to make sure that: /// -/// - `bit_vec` points to a valid `SPBitVec` -/// - the returned memory range is never accessed after the passed `SPBitVec` has been freed -/// - the returned memory range is never accessed concurrently, either via the `SPBitVec` or directly +/// - `bit_vec` points to a valid [SPBitVec] +/// - the returned memory range is never accessed after the passed [SPBitVec] has been freed +/// - the returned memory range is never accessed concurrently, either via the [SPBitVec] or directly #[no_mangle] pub unsafe extern "C" fn sp_bit_vec_unsafe_data_ref( bit_vec: *mut SPBitVec, ) -> SPByteSlice { + assert!(!bit_vec.is_null()); let data = (*bit_vec).0.as_raw_mut_slice(); SPByteSlice { start: data.as_mut_ptr_range().start, diff --git a/crates/servicepoint_binding_c/src/brightness_grid.rs b/crates/servicepoint_binding_c/src/brightness_grid.rs index a34ecf2..33662ff 100644 --- a/crates/servicepoint_binding_c/src/brightness_grid.rs +++ b/crates/servicepoint_binding_c/src/brightness_grid.rs @@ -110,7 +110,7 @@ pub unsafe extern "C" fn sp_brightness_grid_clone( /// /// - `brightness_grid` points to a valid `SPBrightnessGrid` /// - `brightness_grid` is not used concurrently or after this call -/// - `brightness_grid` was not passed to another consuming function, e.g. to create a `SPCommand` +/// - `brightness_grid` was not passed to another consuming function, e.g. to create a [SPCommand] #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_free( brightness_grid: *mut SPBrightnessGrid, @@ -163,7 +163,7 @@ pub unsafe extern "C" fn sp_brightness_grid_get( /// /// The caller has to make sure that: /// -/// - `brightness_grid` points to a valid `SPBitVec` +/// - `brightness_grid` points to a valid [SPBitVec] /// - `brightness_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_brightness_grid_set( diff --git a/crates/servicepoint_binding_c/src/command.rs b/crates/servicepoint_binding_c/src/command.rs index d98b99f..7bc956a 100644 --- a/crates/servicepoint_binding_c/src/command.rs +++ b/crates/servicepoint_binding_c/src/command.rs @@ -1,4 +1,4 @@ -//! C functions for interacting with `SPCommand`s +//! C functions for interacting with [SPCommand]s //! //! prefix `sp_command_` @@ -15,7 +15,7 @@ use crate::{ /// /// This struct and associated functions implement the UDP protocol for the display. /// -/// To send a `SPCommand`, use a `SPConnection`. +/// To send a [SPCommand], use a `SPConnection`. /// /// # Examples /// @@ -31,11 +31,11 @@ impl Clone for SPCommand { } } -/// Tries to turn a `SPPacket` into a `SPCommand`. +/// Tries to turn a `SPPacket` into a [SPCommand]. /// /// The packet is deallocated in the process. /// -/// Returns: pointer to new `SPCommand` instance or NULL +/// Returns: pointer to new [SPCommand] instance or NULL /// /// # Safety /// @@ -44,7 +44,7 @@ impl Clone for SPCommand { /// - `SPPacket` points to a valid instance of `SPPacket` /// - `SPPacket` is not used concurrently or after this call /// - the result is checked for NULL -/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or +/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_try_from_packet( @@ -57,15 +57,15 @@ pub unsafe extern "C" fn sp_command_try_from_packet( } } -/// Clones a `SPCommand` instance. +/// Clones a [SPCommand] instance. /// /// # Safety /// /// The caller has to make sure that: /// -/// - `command` points to a valid instance of `SPCommand` +/// - `command` points to a valid instance of [SPCommand] /// - `command` is not written to concurrently -/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or +/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_clone( @@ -90,7 +90,7 @@ pub unsafe extern "C" fn sp_command_clone( /// /// The caller has to make sure that: /// -/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or +/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_clear() -> *mut SPCommand { @@ -107,7 +107,7 @@ pub unsafe extern "C" fn sp_command_clear() -> *mut SPCommand { /// /// The caller has to make sure that: /// -/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or +/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_hard_reset() -> *mut SPCommand { @@ -122,7 +122,7 @@ pub unsafe extern "C" fn sp_command_hard_reset() -> *mut SPCommand { /// /// The caller has to make sure that: /// -/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or +/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_fade_out() -> *mut SPCommand { @@ -141,7 +141,7 @@ pub unsafe extern "C" fn sp_command_fade_out() -> *mut SPCommand { /// /// The caller has to make sure that: /// -/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or +/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_brightness( @@ -166,7 +166,7 @@ pub unsafe extern "C" fn sp_command_brightness( /// /// - `grid` points to a valid instance of `SPBrightnessGrid` /// - `grid` is not used concurrently or after this call -/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or +/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_char_brightness( @@ -186,9 +186,9 @@ pub unsafe extern "C" fn sp_command_char_brightness( /// The screen will continuously overwrite more pixel data without regarding the offset, meaning /// once the starting row is full, overwriting will continue on column 0. /// -/// The contained `SPBitVec` is always uncompressed. +/// The contained [SPBitVec] is always uncompressed. /// -/// The passed `SPBitVec` gets consumed. +/// The passed [SPBitVec] gets consumed. /// /// Returns: a new `Command::BitmapLinear` instance. Will never return NULL. /// @@ -196,10 +196,10 @@ pub unsafe extern "C" fn sp_command_char_brightness( /// /// The caller has to make sure that: /// -/// - `bit_vec` points to a valid instance of `SPBitVec` +/// - `bit_vec` points to a valid instance of [SPBitVec] /// - `bit_vec` is not used concurrently or after this call /// - `compression` matches one of the allowed enum values -/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or +/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear( @@ -220,9 +220,9 @@ pub unsafe extern "C" fn sp_command_bitmap_linear( /// The screen will continuously overwrite more pixel data without regarding the offset, meaning /// once the starting row is full, overwriting will continue on column 0. /// -/// The contained `SPBitVec` is always uncompressed. +/// The contained [SPBitVec] is always uncompressed. /// -/// The passed `SPBitVec` gets consumed. +/// The passed [SPBitVec] gets consumed. /// /// Returns: a new `Command::BitmapLinearAnd` instance. Will never return NULL. /// @@ -230,10 +230,10 @@ pub unsafe extern "C" fn sp_command_bitmap_linear( /// /// The caller has to make sure that: /// -/// - `bit_vec` points to a valid instance of `SPBitVec` +/// - `bit_vec` points to a valid instance of [SPBitVec] /// - `bit_vec` is not used concurrently or after this call /// - `compression` matches one of the allowed enum values -/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or +/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_and( @@ -254,9 +254,9 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and( /// The screen will continuously overwrite more pixel data without regarding the offset, meaning /// once the starting row is full, overwriting will continue on column 0. /// -/// The contained `SPBitVec` is always uncompressed. +/// The contained [SPBitVec] is always uncompressed. /// -/// The passed `SPBitVec` gets consumed. +/// The passed [SPBitVec] gets consumed. /// /// Returns: a new `Command::BitmapLinearOr` instance. Will never return NULL. /// @@ -264,10 +264,10 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_and( /// /// The caller has to make sure that: /// -/// - `bit_vec` points to a valid instance of `SPBitVec` +/// - `bit_vec` points to a valid instance of [SPBitVec] /// - `bit_vec` is not used concurrently or after this call /// - `compression` matches one of the allowed enum values -/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or +/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_or( @@ -288,9 +288,9 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or( /// The screen will continuously overwrite more pixel data without regarding the offset, meaning /// once the starting row is full, overwriting will continue on column 0. /// -/// The contained `SPBitVec` is always uncompressed. +/// The contained [SPBitVec] is always uncompressed. /// -/// The passed `SPBitVec` gets consumed. +/// The passed [SPBitVec] gets consumed. /// /// Returns: a new `Command::BitmapLinearXor` instance. Will never return NULL. /// @@ -298,10 +298,10 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_or( /// /// The caller has to make sure that: /// -/// - `bit_vec` points to a valid instance of `SPBitVec` +/// - `bit_vec` points to a valid instance of [SPBitVec] /// - `bit_vec` is not used concurrently or after this call /// - `compression` matches one of the allowed enum values -/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or +/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_xor( @@ -334,7 +334,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_xor( /// /// - `grid` points to a valid instance of `SPCp437Grid` /// - `grid` is not used concurrently or after this call -/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or +/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_cp437_data( @@ -362,7 +362,7 @@ pub unsafe extern "C" fn sp_command_cp437_data( /// - `pixel_grid` points to a valid instance of `SPPixelGrid` /// - `pixel_grid` is not used concurrently or after this call /// - `compression` matches one of the allowed enum values -/// - the returned `SPCommand` instance is freed in some way, either by using a consuming function or +/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_command_free`. #[no_mangle] pub unsafe extern "C" fn sp_command_bitmap_linear_win( @@ -381,7 +381,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win( )))) } -/// Deallocates a `SPCommand`. +/// Deallocates a [SPCommand]. /// /// # Examples /// @@ -394,7 +394,7 @@ pub unsafe extern "C" fn sp_command_bitmap_linear_win( /// /// The caller has to make sure that: /// -/// - `command` points to a valid `SPCommand` +/// - `command` points to a valid [SPCommand] /// - `command` is not used concurrently or after this call /// - `command` was not passed to another consuming function, e.g. to create a `SPPacket` #[no_mangle] diff --git a/crates/servicepoint_binding_c/src/connection.rs b/crates/servicepoint_binding_c/src/connection.rs index 846b607..ee630a9 100644 --- a/crates/servicepoint_binding_c/src/connection.rs +++ b/crates/servicepoint_binding_c/src/connection.rs @@ -67,7 +67,7 @@ pub unsafe extern "C" fn sp_connection_send_packet( (*connection).0.send((*packet).0).is_ok() } -/// Sends a `SPCommand` to the display using the `SPConnection`. +/// Sends a [SPCommand] to the display using the `SPConnection`. /// /// The passed `command` gets consumed. /// diff --git a/crates/servicepoint_binding_c/src/cp437_grid.rs b/crates/servicepoint_binding_c/src/cp437_grid.rs index 781c345..38d4af0 100644 --- a/crates/servicepoint_binding_c/src/cp437_grid.rs +++ b/crates/servicepoint_binding_c/src/cp437_grid.rs @@ -101,7 +101,7 @@ pub unsafe extern "C" fn sp_cp437_grid_clone( /// /// - `cp437_grid` points to a valid `SPCp437Grid` /// - `cp437_grid` is not used concurrently or after cp437_grid call -/// - `cp437_grid` was not passed to another consuming function, e.g. to create a `SPCommand` +/// - `cp437_grid` was not passed to another consuming function, e.g. to create a [SPCommand] #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_free(cp437_grid: *mut SPCp437Grid) { _ = Box::from_raw(cp437_grid); @@ -151,7 +151,7 @@ pub unsafe extern "C" fn sp_cp437_grid_get( /// /// The caller has to make sure that: /// -/// - `cp437_grid` points to a valid `SPBitVec` +/// - `cp437_grid` points to a valid [SPBitVec] /// - `cp437_grid` is not written to or read from concurrently #[no_mangle] pub unsafe extern "C" fn sp_cp437_grid_set( diff --git a/crates/servicepoint_binding_c/src/packet.rs b/crates/servicepoint_binding_c/src/packet.rs index 5dc5820..d8a0302 100644 --- a/crates/servicepoint_binding_c/src/packet.rs +++ b/crates/servicepoint_binding_c/src/packet.rs @@ -9,8 +9,8 @@ use crate::SPCommand; /// The raw packet pub struct SPPacket(pub(crate) servicepoint::packet::Packet); -/// Turns a `SPCommand` into a `SPPacket`. -/// The `SPCommand` gets consumed. +/// Turns a [SPCommand] into a `SPPacket`. +/// The [SPCommand] gets consumed. /// /// Will never return NULL. /// @@ -18,8 +18,8 @@ pub struct SPPacket(pub(crate) servicepoint::packet::Packet); /// /// The caller has to make sure that: /// -/// - `SPCommand` points to a valid instance of `SPCommand` -/// - `SPCommand` is not used concurrently or after this call +/// - [SPCommand] points to a valid instance of [SPCommand] +/// - [SPCommand] is not used concurrently or after this call /// - the returned `SPPacket` instance is freed in some way, either by using a consuming function or /// by explicitly calling `sp_packet_free`. #[no_mangle] diff --git a/crates/servicepoint_binding_c/src/pixel_grid.rs b/crates/servicepoint_binding_c/src/pixel_grid.rs index 780c305..e032d50 100644 --- a/crates/servicepoint_binding_c/src/pixel_grid.rs +++ b/crates/servicepoint_binding_c/src/pixel_grid.rs @@ -108,7 +108,7 @@ pub unsafe extern "C" fn sp_pixel_grid_clone( /// /// - `pixel_grid` points to a valid `SPPixelGrid` /// - `pixel_grid` is not used concurrently or after pixel_grid call -/// - `pixel_grid` was not passed to another consuming function, e.g. to create a `SPCommand` +/// - `pixel_grid` was not passed to another consuming function, e.g. to create a [SPCommand] #[no_mangle] pub unsafe extern "C" fn sp_pixel_grid_free(pixel_grid: *mut SPPixelGrid) { _ = Box::from_raw(pixel_grid);