Slices
Rust has really nice handling of slices of memory.
Let's create a new project:
cargo new ex18 --lib
Now setup a tree like this:
.
├── c
│ ├── build_linux.sh
│ ├── ex18.c
├── Cargo.toml
└── src
└── lib.rs
Don't forget that Cargol.toml needs to specify your crate type:
[lib]
crate-type = ["staticlib"] # Will create a .so on Linux, .dylib on Mac, .dll on Windows
Our Rust file (lib.rs) is designed to illustrate working with slices:
#![allow(unused)] fn main() { // We're using "no_mangle" to ensure function names are preserved #[no_mangle] // Don't forget extern "C"! pub extern "C" fn sum_byte_slice( ptr: *const u8, // A raw pointer to bytes. length: usize, // Length, in bytes. ) -> i32 { // Always a good idea to do a null pointer check if ptr.is_null() || length == 0 { return 0; } // Slices ARE a pointer and a length! let slice = unsafe { std::slice::from_raw_parts(ptr, length) }; // Now we can work as normal safe code let mut sum: i32 = 0; for &num in slice { sum += num as i32; } sum } }
Notice that the ONLY unsafe part is the
from_raw_parts. There's a few caveats withfrom_raw_parts; you need to be using the same memory alignment as the C compiler, the slice can't span multiple allocations. And of course, if the C program sends you an invalid length then you can expect all manner of trouble.