Struct std::ffi::CString 1.0.0[−][src]
pub struct CString { /* fields omitted */ }
Expand description
一种类型,表示拥有的,C 兼容的,以 nul 终止的字符串,中间没有 nul 字节。
此类型的目的是能够从 Rust 字节切片或 vector 安全地生成 C 兼容字符串。
此类型的一个实例是静态保证,底层字节不包含内部 0 字节 (nul 字符
),并且最后一个字节为 0 (nul 终止符
)。
CString
对 &CStr
就像对 String
对 &str
一样: 每对中的前者是拥有的字符串; 后者是借用的。
创建一个 CString
CString
是从字节片或字节 vector 或任何实现 Into
<
Vec
<
u8
>>
的文件创建的 (例如,您可以直接从 String
或 &str
构建 CString
,因为两者都实现了 trait)。
CString::new
方法实际上将检查所提供的 &[u8]
中间是否没有 0 字节,如果找到一个,则返回错误。
将裸指针提取到整个 C 字符串
CString
通过 Deref
trait 实现 as_ptr
方法。此方法将为您提供 *const c_char
,您可以直接将其输入期望包含以 N 结束的字符串的 extern 函数,例如 C 的 strdup()
。
注意,as_ptr
返回一个只读指针。如果 C 代码写入它,则会导致未定义的行为。
提取整个 C 字符串的片段
或者,您可以使用 CString::as_bytes
方法从 CString
获得 &[
u8
]
切片。以这种方式产生的切片不包含尾随 nul 终止符。
当您要调用带有 *const u8
参数 (不一定是 nul 终止) 的 extern 函数,以及带有字符串长度的另一个参数 (如 C 的 strndup()
) 时,此功能很有用。
当然,您可以使用 len
方法获取切片的长度。
如果需要带有 nul 终止符的 &[
u8
]
切片,则可以改用 CString::as_bytes_with_nul
。
一旦有了所需的切片类型 (带或不带 nul 终止符),就可以调用切片自己的 as_ptr
方法来获取只读的裸指针,以将其传递给 extern 函数。
有关确保裸指针的生命周期的讨论,请参见该函数的文档。
Examples
use std::ffi::CString; use std::os::raw::c_char; extern "C" { fn my_printer(s: *const c_char); } // 我们确定我们的字符串中间没有 0 个字节,因此我们可以 .expect() let c_to_print = CString::new("Hello, world!").expect("CString::new failed"); unsafe { my_printer(c_to_print.as_ptr()); }Run
Safety
CString
用于处理传统的 C 样式字符串 (由单个 nul 字节终止的非 nul 字节序列) ; 这些类型的字符串的主要用例是与类似 C 的代码进行互操作。
通常,您将需要转让该外部代码的所有权 to/from。
强烈建议您在使用 CString
之前通读 CString
文档,因为对 CString
实例的所有权管理不当会导致无效的内存访问,内存泄漏和其他内存错误。
Implementations
从字节容器创建一个新的 C 兼容字符串。
此函数将使用提供的数据,并使用基础字节构造新的字符串,从而确保尾随 0 字节。
此函数的末尾将附加这个 0 字节; 提供的数据不应包含任何 0 字节。
Examples
use std::ffi::CString; use std::os::raw::c_char; extern "C" { fn puts(s: *const c_char); } let to_print = CString::new("Hello!").expect("CString::new failed"); unsafe { puts(to_print.as_ptr()); }Run
Errors
如果提供的字节包含内部 0 字节,则此函数将返回错误。
返回的 NulError
将包含字节以及 nul 字节的位置。
通过使用字节 vector 来创建 C 兼容字符串,而无需检查内部 0 字节。
此方法等效于 CString::new
,除了不进行运行时断言,即 v
不包含 0 字节,并且它需要实际的字节 vector,而不是可以使用 Into 转换为 1 的任何内容。
Examples
use std::ffi::CString; let raw = b"foo".to_vec(); unsafe { let c_string = CString::from_vec_unchecked(raw); }Run
重新获得通过 CString::into_raw
转移到 C 的 CString
的所有权。
此外,将根据指针重新计算字符串的长度。
Safety
仅应使用先前通过调用 CString::into_raw
获得的指针进行调用。
其他用法 (例如,尝试获取由外来代码分配的字符串的所有权) 可能导致未定义的行为或分配器损坏。
应该注意的是,长度不仅是 “recomputed,”,而且重新计算的长度必须与 CString::into_raw
调用的原始长度匹配。
这意味着在将字符串传递到可以修改字符串长度的 C 函数时,不应使用 CString::into_raw
/from_raw
方法。
Note: 如果您需要借用由 外码,请使用
CStr
。如果您需要拥有 由外来代码分配的字符串,您将需要 制定自己的规定以适当地,可能地释放它 使用外来代码的 API 来做到这一点。
Examples
创建一个 CString
,将所有权传递给 extern
函数 (通过裸指针),然后使用 from_raw
重新获得所有权:
use std::ffi::CString; use std::os::raw::c_char; extern "C" { fn some_extern_function(s: *mut c_char); } let c_string = CString::new("Hello!").expect("CString::new failed"); let raw = c_string.into_raw(); unsafe { some_extern_function(raw); let c_string = CString::from_raw(raw); }Run
消耗 CString
,并将字符串的所有权转让给 C 调用者。
此函数返回的指针必须返回到 Rust,并使用 CString::from_raw
进行重构以正确释放。
具体来说,应该 不要 使用标准的 C free()
函数来释放该字符串。
未能调用 CString::from_raw
将导致内存泄漏。
C 端必须不修改字符串的长度 (通过在字符串内某处写入 null
或删除最后一个),然后使用 CString::from_raw
将其返回到 Rust。
请参见 CString::from_raw
中的安全性部分。
Examples
use std::ffi::CString; let c_string = CString::new("foo").expect("CString::new failed"); let ptr = c_string.into_raw(); unsafe { assert_eq!(b'f', *ptr as u8); assert_eq!(b'o', *ptr.offset(1) as u8); assert_eq!(b'o', *ptr.offset(2) as u8); assert_eq!(b'\0', *ptr.offset(3) as u8); // 重新获得指向空闲内存的指针 let _ = CString::from_raw(ptr); }Run
如果 CString
包含有效的 UTF-8 数据,则将其转换为 String
。
失败时,将返回原始 CString
的所有权。
Examples
use std::ffi::CString; let valid_utf8 = vec![b'f', b'o', b'o']; let cstring = CString::new(valid_utf8).expect("CString::new failed"); assert_eq!(cstring.into_string().expect("into_string() call failed"), "foo"); let invalid_utf8 = vec![b'f', 0xff, b'o', b'o']; let cstring = CString::new(invalid_utf8).expect("CString::new failed"); let err = cstring.into_string().err().expect("into_string().err() failed"); assert_eq!(err.utf8_error().valid_up_to(), 1);Run
等效于 CString::into_bytes()
,除了返回的 vector 包括结尾的 nul 终止符。
Examples
use std::ffi::CString; let c_string = CString::new("foo").expect("CString::new failed"); let bytes = c_string.into_bytes_with_nul(); assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']);Run
以字节片形式返回此 CString
的内容。
返回的切片不包含尾随 nul 终止符,并且保证不包含任何内部 nul 字节。
如果需要 nul 终止符,请改用 CString::as_bytes_with_nul
。
Examples
use std::ffi::CString; let c_string = CString::new("foo").expect("CString::new failed"); let bytes = c_string.as_bytes(); assert_eq!(bytes, &[b'f', b'o', b'o']);Run
等效于 CString::as_bytes()
,但返回的切片包括结尾的 nul 终止符。
Examples
use std::ffi::CString; let c_string = CString::new("foo").expect("CString::new failed"); let bytes = c_string.as_bytes_with_nul(); assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']);Run
pub fn into_boxed_c_str(self) -> Box<CStr>ⓘNotable traits for Box<I, A>impl<I, A> Iterator for Box<I, A> where
I: Iterator + ?Sized,
A: Allocator, type Item = <I as Iterator>::Item;impl<F, A> Future for Box<F, A> where
F: Future + Unpin + ?Sized,
A: Allocator + 'static, type Output = <F as Future>::Output;impl<R: Read + ?Sized> Read for Box<R>impl<W: Write + ?Sized> Write for Box<W>
1.20.0[src]
pub fn into_boxed_c_str(self) -> Box<CStr>ⓘNotable traits for Box<I, A>impl<I, A> Iterator for Box<I, A> where
I: Iterator + ?Sized,
A: Allocator, type Item = <I as Iterator>::Item;impl<F, A> Future for Box<F, A> where
F: Future + Unpin + ?Sized,
A: Allocator + 'static, type Output = <F as Future>::Output;impl<R: Read + ?Sized> Read for Box<R>impl<W: Write + ?Sized> Write for Box<W>
1.20.0[src]impl<I, A> Iterator for Box<I, A> where
I: Iterator + ?Sized,
A: Allocator, type Item = <I as Iterator>::Item;impl<F, A> Future for Box<F, A> where
F: Future + Unpin + ?Sized,
A: Allocator + 'static, type Output = <F as Future>::Output;impl<R: Read + ?Sized> Read for Box<R>impl<W: Write + ?Sized> Write for Box<W>
将 Vec
<u8>
转换为 CString
,而不检查给定 Vec
的不变式。
Safety
给定的 Vec
必须最后一个元素为一个 nul 字节。
这意味着它不能为空,也不能在其他任何地方有任何其他 nul 字节。
Example
#![feature(cstring_from_vec_with_nul)] use std::ffi::CString; assert_eq!( unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) }, unsafe { CString::from_vec_unchecked(b"abc".to_vec()) } );Run
存在运行时检查以确保 Vec
(它的最后一个元素) 中只有一个 nul 字节。
Errors
如果存在 nul 字节而不是最后一个元素,或者不存在 nul 字节,则将返回错误。
Examples
如果调用成功而没有结尾的 nul 字节,则转换将产生与 CString::new
相同的结果。
#![feature(cstring_from_vec_with_nul)] use std::ffi::CString; assert_eq!( CString::from_vec_with_nul(b"abc\0".to_vec()) .expect("CString::from_vec_with_nul failed"), CString::new(b"abc".to_vec()).expect("CString::new failed") );Run
格式错误的 Vec
将产生错误。
#![feature(cstring_from_vec_with_nul)] use std::ffi::{CString, FromVecWithNulError}; // 内部 nul 字节 let _: FromVecWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err(); // 无空字节 let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err();Run
Methods from Deref<Target = CStr>
返回此 C 字符串的内部指针。
返回的指针在 self
内一直有效,并且指向以 0 字节结尾的连续区域,以表示字符串的结尾。
WARNING
返回的指针是只读的; 对其进行写入 (包括将其传递给进行写入的 C 代码) 会导致未定义的行为。
您有责任确保底层内存不会过早释放。例如,当在 unsafe
块中使用 ptr
时,以下代码将导致未定义的行为:
use std::ffi::CString; let ptr = CString::new("Hello").expect("CString::new failed").as_ptr(); unsafe { // `ptr` 是悬垂的 *ptr; }Run
发生这种情况是因为 as_ptr
返回的指针不携带任何生命周期信息,并且在评估 CString::new("Hello").expect("CString::new failed").as_ptr()
表达式后立即释放了 CString
。
要解决此问题,请将 CString
绑定到本地变量:
use std::ffi::CString; let hello = CString::new("Hello").expect("CString::new failed"); let ptr = hello.as_ptr(); unsafe { // `ptr` 有效,因为 `hello` 在作用域中 *ptr; }Run
这样,hello
中 CString
的生命周期包含 ptr
和 unsafe
块的生命周期。
将此 C 字符串转换为包含尾随 0 字节的字节切片。
此函数与 CStr::to_bytes
等效,除了保留尾随的 nul 终止符而不是将其截断之外。
Note: 目前,此方法已实现为零费用强制转换,但是 计划在 future 中更改其定义以执行 每次调用此方法时的长度计算。
Examples
use std::ffi::CStr; let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); assert_eq!(cstr.to_bytes_with_nul(), b"foo\0");Run
如果 CStr
的内容是有效的 UTF-8 数据,则此函数将返回带有相应 &str
切片的 Cow
::
Borrowed
(
&str
)
。
否则,它将用 U+FFFD REPLACEMENT CHARACTER
替换所有无效的 UTF-8 序列,并返回带有结果的 Cow
::
Owned
(
String
)
。
Examples
在包含有效 UTF-8 的 CStr
上调用 to_string_lossy
:
use std::borrow::Cow; use std::ffi::CStr; let cstr = CStr::from_bytes_with_nul(b"Hello World\0") .expect("CStr::from_bytes_with_nul failed"); assert_eq!(cstr.to_string_lossy(), Cow::Borrowed("Hello World"));Run
在包含无效 UTF-8 的 CStr
上调用 to_string_lossy
:
use std::borrow::Cow; use std::ffi::CStr; let cstr = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0") .expect("CStr::from_bytes_with_nul failed"); assert_eq!( cstr.to_string_lossy(), Cow::Owned(String::from("Hello �World")) as Cow<'_, str> );Run
Trait Implementations
fn from(s: CString) -> Box<CStr>ⓘNotable traits for Box<I, A>impl<I, A> Iterator for Box<I, A> where
I: Iterator + ?Sized,
A: Allocator, type Item = <I as Iterator>::Item;impl<F, A> Future for Box<F, A> where
F: Future + Unpin + ?Sized,
A: Allocator + 'static, type Output = <F as Future>::Output;impl<R: Read + ?Sized> Read for Box<R>impl<W: Write + ?Sized> Write for Box<W>
[src]
fn from(s: CString) -> Box<CStr>ⓘNotable traits for Box<I, A>impl<I, A> Iterator for Box<I, A> where
I: Iterator + ?Sized,
A: Allocator, type Item = <I as Iterator>::Item;impl<F, A> Future for Box<F, A> where
F: Future + Unpin + ?Sized,
A: Allocator + 'static, type Output = <F as Future>::Output;impl<R: Read + ?Sized> Read for Box<R>impl<W: Write + ?Sized> Write for Box<W>
[src]impl<I, A> Iterator for Box<I, A> where
I: Iterator + ?Sized,
A: Allocator, type Item = <I as Iterator>::Item;impl<F, A> Future for Box<F, A> where
F: Future + Unpin + ?Sized,
A: Allocator + 'static, type Output = <F as Future>::Output;impl<R: Read + ?Sized> Read for Box<R>impl<W: Write + ?Sized> Write for Box<W>