A typical pattern for accessing a C API involves allocating a struct that holds API stateyness and then calling an init() function of some sort while passing a pointer to struct to it.There are variations on this theme but it's a pretty common one to encounter when dealing with a C library. It's (relatively) straightforward to generate bindings in Rust to call C functions, compared to other languages, you did good with that. This is a snippet from code that runs.
{
// you can't just alloc a struct on the stack without initing.
// every single field inside the struct must be initted, even if you know you're
// going to call an init function to set the struct to a known good state.
// make sure to set it to writable with mut too, once you decl something, all you
// can do is read from it by default.
// welcome to Rust
let mut hash_state:SHA256_CTX = SHA256_CTX { h: [0; 8usize],
Nl: 0,
Nh: 0,
data: [0; 16usize],
num: 0,
md_len: 0 };
do_hash_init(&mut hash_state);
}
fn do_hash_init( h: &mut SHA256_CTX ) {
unsafe {
let rc = SHA256_Init(h);
if rc != 1 {
panic!("SHA256_Init() failed, reason = {}", rc);
}
}
}
-
I really really really would rather not know what's exactly in that C-struct, and the API provides a call to initialize it to a known good state anyway, so zeroing it all out field by field by field is not only a pain but pointless as well. If the API changes and they add more fields to it, it's yet another place that changes have to be made which is a place where bugs can happen.
-
If zeroing it out is required no matter what, is there a terser way or doing it? What if that struct had 5x as many fields inside it? You are really going to require that they all get initialized one by one?
-
Yes, there's probably a crate for that. That's not the point, the point is legacy C code that you are obligated to keep using for reasons.