A CStr is a borrowed type and, as such, isn't made "on its own". Below the hood, it isn't much more than a reference to a CString, and can be created from either:
- Borrowing a
CString (obvious). The original (source) CString must not be dropped and the lifetime of CStr is only valid for as long as the source exists
- From a slice of bytes, via
CStr::from_bytes_with_nul. The CStr is only valid for as long as the original slice (which itself is only valid for as long as the source data allocated somewhere)
Creating a CStr through a CString is straightforward:
let cstring:CString = CString::new("foobar".as_bytes()).unwrap();
let cstr:&CStr = cstring.as_c_str();
println!("{:?}", cstr);
Converting an existing slice is also straightforward:
let cstr2:&CStr = CStr::from_bytes_with_nul("foobar\0".as_bytes()).unwrap();
println!("{:?}", cstr2);
Do note that the lifetime of these will evidently, again, depend on the lifetime of whatever you used to create the &CStr - as indicated by the lifetime parameter on its declaration
Kept for posterity: 'static was not a hard requirement
To create a const &'static CStr, you're going to struggle, and you're going to need an external crate for a specific macro (lazy_static), but it is doable, like so:
#[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);
}
The point of lazy_static is to allow function calls when defining static references; we can leverage this to construct our CStr on-the-fly, and since it is a static reference, borrowing it is valid for up to and including 'static. Mission accomplished.