How do I initialize an opaque C struct when using Rust FFI?
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()
}
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:
- What's the Rust idiom to define a field pointing to a C opaque pointer?
- In Rust how can I define or import a C struct from a third party library?
- Allocating an object for C / FFI library calls