Here's what I would like to do in C code:
#include <some_lib.h>
int main() {
some_lib_struct_t x;
some_lib_func(&x);
}
How do I make use of the library in Rust? Here's what I've got so far:
extern crate libc; // 0.2.51
struct some_lib_struct_t;
#[link(name = "some_lib")]
extern "C" {
fn some_lib_func(x: *mut some_lib_struct_t);
}
fn main() {
let mut x: some_lib_struct_t;
unsafe {
some_lib_func(&mut x);
}
}
When compiling I get an error:
error[E0381]: borrow of possibly uninitialized variable: `x`
--> src/main.rs:13:23
|
13 | some_lib_func(&mut x);
| ^^^^^^ use of possibly uninitialized `x`
The safest answer is to initialize the struct yourself:
let mut x: some_lib_struct_t = some_lib_struct_t;
unsafe {
some_lib_func(&mut x);
}
The closest analog to the C code is to use MaybeUninit
use std::mem::MaybeUninit;
unsafe {
let mut x = MaybeUninit::uninit();
some_lib_func(x.as_mut_ptr());
}
Before Rust 1.36, you can use mem::uninitialized
:
unsafe {
let mut x: some_lib_struct_t = std::mem::uninitialized();
some_lib_func(&mut x);
}
You have to be sure that some_lib_func
completely initializes all the members of the struct, otherwise the unsafety will leak outside of the unsafe
block.
Speaking of "members of the struct", I can almost guarantee your code won't do what you want. You've defined some_lib_struct_t
as having zero size. That means that no stack space will be allocated for it, and a reference to it won't be what your C code is expecting.
You need to mirror the definition of the C struct in Rust so that the appropriate size, padding, and alignment can be allocated. Usually, this means using repr(C)
.
Many times, C libraries avoid exposing their internal struct representation by always returning a pointer to the opaque type:
From the documentation for mem::uninitialized()
:
Deprecated since 1.39.0: use
mem::MaybeUninit
instead
The new solution would look like this:
use std::mem::MaybeUninit;
let instance = unsafe {
let mut x: MaybeUninit<some_lib_struct_t> = MaybeUninit::uninit();
some_lib_func(x.as_mut_ptr());
x.assume_init()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With