cargo test
This does the work of pulling ccommon
from GitHub, building it, and running bindgen
to generate the Rust bindings.
This package uses rust-bindgen
to generate all the bindings for ccommon
. Note that these bindings are the core low level FFI bindings needed to call into the C layer. They are not ergonomic Rust, i.e. you have to structure your calls just like you would in C. For example:
// Create a ccommon ring array with an item size of 8 bytes, holding 64 elements.
let ring_array = unsafe { ring_array_create(8, 64) };
// Push a value onto it.
let blort = 31337u64;
let blort_ptr: *const c_void = &blort as *const _ as *const c_void;
let result = unsafe { ring_array_push(blort_ptr, ring_array) };
// Pop a value into a variable.
let mut popped: u64 = 0;
let popped_ptr: *mut c_void = &mut popped as *mut _ as *mut c_void;
let result = unsafe { ring_array_pop(popped_ptr, ring_array) };
// Make sure to free it when you're done with it to avoid memory leaks!
unsafe { ring_array_destroy(ring_array) };
An ergonomic wrapper on top of the generated bindings might look a little more like this:
struct ring_array {
pub ra: *mut ring_array,
}
impl ring_array {
pub fn new<T>(cap: u32) -> ring_array {
let ra = unsafe { ring_array_create(std::mem::size_of::<T>(), cap) };
ring_array {ra}
}
// This would probably return something higher level.
pub fn push<T>(&mut self, item: &T) -> rstatus_i {
let t_ptr: *const c_void = item as *const _ as *const c_void;
unsafe { ring_array_push(t_ptr, self.ra) }
}
// And here you would simply return the item directly rather than passing a parameter,
// but you get my drift.
pub fn pop<T>(&mut self, item: &mut T) -> rstatus_i {
let t_ptr: *mut c_void = item as *mut _ as *mut c_void;
unsafe { ring_array_pop(t_ptr, self.ra) }
}
}
impl Drop for ring_array {
fn drop(&mut self) {
unsafe { ring_array_destroy(self.ra) }
}
}
As of this writing, bindings are generated for all of ccommon
.
The rust-bindgen
project's documentation goes into detail on how to wrap a project, but here is a quick overview of key files in this project.
This is a hook into cargo
that does the work of grabbing ccommon
from GitHub, configuring and building it with cmake
, and generating the bindings.
This C header file gets passed to rust-bindgen
. It serves as the top level include that pulls in all of the other include files from ccommon
.
This is the top level file that contains all of the generated code, as well as a couple of rudimentary tests.
The bindings themselves are in this file. Look here to see the actual method signatures. Pro tip: to see the generated code in your editor, create a symlink since the $BUILD_ID
will change: find target -name bindings.rs -exec ln -sf '{}' ';'
- Write ergonomic wrappers!