Const&'static CStr

问题描述 投票:0回答:1

我没有在标准库中找到有关如何制作const &'static CStr的任何内容。我试图制作自己的宏以将&'static str文字转换为&'static CStr

macro_rules! cstr {
    ($e: expr) => {{
        const buffer: &str = concat!($e, "\0");
        unsafe {std::ffi::CStr::from_bytes_with_nul_unchecked(buffer.as_bytes())}
    }}                                                                           
}     

但是有两个问题:

  1. 在典型情况下,此方法工作正常,但如果expr包含空字节,则会调用未定义的行为
  2. [str::as_bytes不是const,所以&CStr不是const

有什么方法可以创建const &'static CStr

rust ffi
1个回答
0
投票

A CStrborrowed type,因此不是“单独”制作的。在引擎盖下,它只不过是对CString的引用,可以通过以下任一方式创建:

  • 借用CString(显而易见)。不得删除原始(源)CString,并且CString的生存期仅在存在源的情况下才有效
  • 通过CStr,从一个字节的字节开始。 CStr::from_bytes_with_nul仅在原始切片时有效(其本身仅在已分配源数据somewhere时有效)

通过CStr::from_bytes_with_nul创建CStr很简单:

CStr

转换现有切片也很简单:

CString

请注意,它们的生存期显然将取决于您用来创建let cstring:CString = CString::new("foobar".as_bytes()).unwrap(); let cstr:&CStr = cstring.as_c_str(); println!("{:?}", cstr); 的对象的生存期-如其声明中的lifetime参数所指示的


保留后代let cstr2:&CStr = CStr::from_bytes_with_nul("foobar\0".as_bytes()).unwrap(); println!("{:?}", cstr2); 不是硬性要求

要创建&CStr,您会很费力,并且需要一个用于特定宏('static)的外部包装箱,但这是可行的,就像这样:

const &'static CStr

lazy_static的意义是在定义静态引用时允许函数调用;我们可以利用它来即时构建我们的#[macro_use] extern crate lazy_static; use std::ffi::CStr; lazy_static! { static ref FOO:&'static CStr = unsafe { CStr::from_bytes_with_nul_unchecked("foobar\0".as_bytes()) }; } fn test(input: &'static CStr) { println!("{:?}", FOO.to_str()); } fn main() { test(&FOO); } ,并且由于它是静态引用,因此借用它最多可包含lazy_static。任务完成。

© www.soinside.com 2019 - 2024. All rights reserved.