Skip to content

Instantly share code, notes, and snippets.

@stevedoyle
Created February 9, 2023 16:45
Show Gist options
  • Save stevedoyle/39451d0e10a5e62a6db85829b97c2d83 to your computer and use it in GitHub Desktop.
Save stevedoyle/39451d0e10a5e62a6db85829b97c2d83 to your computer and use it in GitHub Desktop.
Rust code for calling C APIs that use opaque pointers
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
include!("../bindings.rs");
fn main() {
unsafe {
let size = fooGetCtxSize();
println!("Ctx Size: {}", size);
// Need to allocate memory to hold the context.
// Can't use the FooState type from bindings.rs since this is an opaque
// type on the interface and it maps to a zero sized structure. Just to
// prove this ...
let fooStateSize = std::mem::size_of::<FooState>();
println!("size_of(FooState) = {}", fooStateSize);
// Approach #1 - Using an uninitialized vector
// Lets start out with a vector with enough capacity to hold the context
let mut ctxbuf: Vec<u8> = Vec::with_capacity(size as usize);
// Then get a pointer to the spare capacity buffer and cast it to a
// pointer of the FooState type.
let state: *mut FooState = ctxbuf.spare_capacity_mut().as_mut_ptr().cast();
let status = fooInitCtx(state);
assert_eq!(0, status);
let status = fooDoSomething(state, 5);
assert_eq!(0, status);
// Approach #2 - Using an initialized vector
// Lets start out with a Vec<u8> of the right size and filled with zeros
// and convert it into a boxed slice ...
let mut buf = vec![0u8; size as usize].into_boxed_slice();
// ... which can then provide a pointer to the buffer memory which can
// be cast to a pointer of the correct type.
let state = buf.as_mut_ptr() as *mut FooState;
let status = fooInitCtx(state);
assert_eq!(0, status);
let status = fooDoSomething(state, 5);
assert_eq!(0, status);
}
println!("Hello, world!");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment