I'm writing a safe Rust layer with which I can call functions from a C library in Rust. I've generated the unsafe bindings using rust-bindgen, but I'm getting a little confused on the differences between how Rust and C work with regards to passing pointers.
The C function looks like this:
bool imeGet(unsigned char address, int *value);
It reads an I2C sensor at address
, stores the result in value
, and returns TRUE
on success.
Bindgen has the Rust function looking like this:
pub fn imeGet(address: ::std::os::raw::c_uchar,
value: *mut ::std::os::raw::c_int) -> bool;
And my safe caller looks like this currently:
pub fn ime_get(addr: u8) -> i32 {
let v: &mut i32 = 0;
unsafe {
imeGet(addr, v);
*v
}
}
This code doesn't compile because of the = 0
. When I didn't have that, the compiler complained about v
possibly not having been initialized. My intent is to handle the success within this function, and just return the i32
value.
How do I handle the behavior of the *mut c_int
argument? I tried to declare v
as a reference and return its dereferenced value (above), but that doesn't work. I also tried to just return v
, but I don't really want the return value to stay mutable.
I'm pretty new to Rust, but I do have a decent background in C, which may be my source of confusion.
The moral equivalent of your Rust code is:
This will have an error because the C code is likely going to dereference that
v
to store the value in, except you've passed in a NULL, so it's more likely to go boom.You need to create storage for the value, then provide a reference to that storage to the function:
The solution for any pointer type uses
ptr::null_mut
:The general solution for any type uses
mem::uninitialized
:For completeness, you should be checking the return value:
There really aren't any, at this level.