简体   繁体   中英

Most appropriate type for opaque extern static in Rust?

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?

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;
}

Playground

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;
}

Playground

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM