How to create a C compatible static string array from &CStr s

I need to have a C-style array of C strings to interface with a C library.

A &CStr seems to have a size of 16 (on 64bit systems), so placing them directly in an array doesn't create a valid array of pointers to C strings.

What I have come up with is the following:

struct CStrPtr(*const i8);

unsafe impl Sync for CStrPtr {}

static STRING_ARR: [CStrPtr; 2] = [
  CStrPtr(c"Item1".as_ptr()),
  CStrPtr(c"Item2".as_ptr())
]

I was wondering if there is a way to achieve this in a more ideomatic/non-unsafe way.

the documentation of CStr suggests *const c_char

Since a c_char is essentially an i8, I think thats what I'm currently using.

It's a u8 on some platforms.

You're also missing a #[repr(transparent)], which rustc also warns about:

warning: `extern` block uses type `CStrPtr`, which is not FFI-safe
  --> src/lib.rs:12:31
   |
12 | unsafe extern "C" { fn f(str: CStrPtr); }
   |                               ^^^^^^^ not FFI-safe
   |
   = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
   = note: this struct has unspecified layout
1 Like

Idiomatic way would be to use *const c_char.

Interaction with FFI is already quite unsafe, but you could make it slightly safer by adding a lifetime to your newtype. You can add PhantomData field that pretends to borrow the CStr. it's a zero-sized field so it won't affect ABI compatibility.

2 Likes