How to avoid a "repr(C)" warning when I bring in a Rust-side opaque struct back from C?


#1

I have some Rust structs that are made visible to C code via opaque pointers. The C code just passes these pointers around and never needs to dereference them. I provide new/free functions for the C code to use, and of course functions which actually do some work with this struct.

// This is explicitly not #[repr(C)] since it is meant to be opaque
struct MyRustStruct {
    ...
}

#[no_mangle]
pub extern fn my_rust_struct_new() -> *const MyRustStruct {
    Box::into_raw(Box::new(MyRustStruct { ... }))
}

#[no_mangle]
pub extern fn my_rust_struct_free(x: *mut MyRustStruct) {
    unsafe { Box::from_raw(x); }
}

Sometimes, for the Rust code to get access to this struct, I need to call a C function that will get me that pointer back from somewhere:

extern "C" fn get_the_struct_from_some_c_context(...) -> *mut MyRustStruct;

However, for each of these declarations of C-side extern functions, I get a warning like this on the return value, which corresponds to my Rust-side opaque struct:

warning: found enum without foreign-function-safe representation annotation in foreign module, consider adding a #[repr(...)] attribute to the type
   --> src/state.rs:120:58
    |
120 |     extern "C" fn rsvg_state_get_stroke(state: *const RsvgState) -> *const PaintServer;
    |                                                                     ^^^^^^^^^^^^^^^^^^

How can I tell the compiler that even if I got a pointer to that struct from an extern function, the external code does not need to dereference it, and thus I don’t need to #[repr©] my struct?


#2

I think you cut off the next part of the compiler warning, which tells you what needs to happen:

  = note: #[warn(improper_ctypes)] on by default

So, just add a #[allow(improper_ctypes)] attribute to the extern block and the warning will go away.


#3

Aha! I was on rustc 1.23 and wasn’t getting that extra bit. With nightly it tells me about either #[repr©] or #[repr(transparent)].

Thanks for the tip - with improper_ctypes now I have no warnings :slight_smile: