如何通过FFI公开编译时生成的静态C字符串?

Mic*_*rer 3 ffi rust

我正在尝试将版本号嵌入库中.理想情况下,这应该是一个可以读取的静态C字符串,并且不需要任何额外的分配来读取版本号.

在Rust方面,我vergen用来生成这样的版本控制信息:

pub static VERSION: &str = env!("VERGEN_SEMVER");
Run Code Online (Sandbox Code Playgroud)

我想最终得到类似的东西

#[no_mangle]
pub static VERSION_C: *const u8 = ... ;
Run Code Online (Sandbox Code Playgroud)

似乎有一种方法可以使用字符串文字来实现这一点,但我还没有找到一种方法来使用编译时字符串.创建一个新的CString似乎超出了静态变量的当前功能,并且往往以错误E0015结束.

只要它没有分配新的内存,像这样返回指针的函数是可以接受的.

#[no_mangle]
pub extern "C" fn get_version() -> *const u8 {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

变量的最终类型(或函数的返回类型)不必基于u8,但应该是可翻译的cbindgen.如果其他一些FFI类型更合适,使用它是完全正常的.

E_n*_*ate 6

通过确保静态字符串切片与C样式字符串兼容(例如,它以空终止符字节结束\0),我们可以安全地获取指向切片开头的指针并将其传递到边界.

pub static VERSION: &str = concat!(env!("VERGEN_SEMVER"), "\0");

#[no_mangle]
pub extern "C" fn get_version() -> *const c_char {
    VER.as_ptr() as *const c_char
}
Run Code Online (Sandbox Code Playgroud)

这是Playground中的一个示例,我使用包的版本作为环境变量来获取并调用Rust中的函数.