Reputation: 125855
I want to obtain a raw pointer to an FFI-defined static, whose concrete type is opaque to Rust.
This is what I currently have:
use std::{ffi::c_void, ptr::addr_of};
fn ptr_to_foo() -> *const c_void {
extern "C" {
static FOO: /* what type here? */;
}
unsafe { addr_of!(FOO).cast() }
}
But with what type should FOO
be declared?
Is it UB to declare it c_void
, given that the bytes at the memory location may not be valid for that type—even though I only create a raw pointer to that location without ever constructing a reference (or worse, dereferencing the pointer/reading the memory)?
If so, is there anything more suitable/appropriate than u8
or would that (or a newtype around it) be the recommended approach?
Upvotes: 0
Views: 363
Reputation: 2654
If you're on nightly, use extern types. They are a nightly-only method to create a dynamically sized type that the compiler knows it can't dereference under any circumstance and are specifically designed for use in ffi.
#![feature(extern_types)]
extern "C"{
type Foo;
static FOO: Foo;
}
The other option is to use a zero-sized type with a private field and no public constructor:
#[repr(C)]
struct Foo{
_inner: [u8;0]
}
extern "C"{
static FOO: Foo;
}
ZST reads and writes are always valid if the pointer you are using is non-null, well-aligned, and not pointing toward deallocated memory, so while you can still read from the static, doing so is well-defined. The only thing to be careful of is that casting the returned pointers into mutable references will result in undefined behavior if they are aliased, but that's an issue with statics, rather than the types.
Upvotes: 1