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

时间:2018-12-04 10:44:45

标签: rust ffi

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

在Rust方面,我正在使用vergen生成如下版本信息:

pub static VERSION: &str = env!("VERGEN_SEMVER");

最后我想得到类似

#[no_mangle]
pub static VERSION_C: *const u8 = ... ;

似乎有一种使用string literals来实现这一目标的方法,但是我还没有找到一种使用编译时间字符串来实现这一目标的方法。创建新的CString似乎超出了静态变量的当前功能,并且往往以error E0015结尾。

这样的返回指针的函数是可以接受的,只要它不分配新的内存即可。

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

变量的最终类型(或函数的返回类型)不必基于u8,但可以通过cbindgen进行翻译。如果其他一些FFI类型更合适,则使用它就可以了。

1 个答案:

答案 0 :(得分: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
}

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