问题
I want to have a Rust library expose a const char *
static string to C, to be compatible with an existing interface (specifically librsync). That is, the C header file has
extern char const *my_string;
In C, the library would simply have
char const *my_string = "hi";
In Rust I've tried something like
pub static my_string: *const libc::c_char = unsafe { "hi\0" as *const libc::c_char };
but this complains
error: casting `&'static str` as `*const i8` is invalid
It seems like I can't use CString
etc because they won't be a compile-time constant expression.
回答1:
This gets a little weird, so bear with me...
#[repr(C)]
pub struct StaticCString(*const u8);
unsafe impl Sync for StaticCString {}
#[no_mangle]
pub static CONST_C_STR: StaticCString =
StaticCString(b"a constant c string\0" as *const u8);
Ideally, we could just have a public, static, unmangled, constant pointer to some bytes, right? However, you cannot do that as you get this error:
error: the trait `core::marker::Sync` is not implemented for the type `*const u8` [E0277]
pub static CONST_C_STR: *const u8 = b"a constant c string\0" as *const u8;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I've not spent a deep amount of time thinking through why this would be the case. It seems like an immutable pointer shouldn't cause too much trouble...
However, we can tell the compiler that our type is safe to use in a multi-threaded environment. That's why the wrapper type exists - it allows us to implement Sync
for a type that we own. A single-element struct should always have the same implementation as the wrapped value, but we go ahead and mark it as repr(C)
to be on the safe side.
This worked with a simple C program:
#include <stdio.h>
extern char * CONST_C_STR;
int main(int argc, char *argv[]) {
printf("%s\n", CONST_C_STR);
}
回答2:
The crate c_str_macro provides a convenience macro c_str!
, which appends a 0 byte to a Rust string literal and presents it as a CStr
reference.
Disclaimer: I'm the author of the crate.
来源:https://stackoverflow.com/questions/33850189/how-to-publish-a-constant-string-in-the-rust-ffi