How to publish a constant string in the Rust FFI?

对着背影说爱祢 提交于 2019-12-22 05:27:10

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!