Struct alloc::ffi::CString

1.64.0 · source ·
pub struct CString { /* private fields */ }
Expand description

一种类型,表示拥有的,C 兼容的,以 nul 终止的字符串,中间没有 nul 字节。

此类型的目的是能够从 Rust 字节切片或 vector 安全地生成 C 兼容字符串。 此类型的一个实例是静态保证,底层字节不包含内部 0 字节 (nul 字符),并且最后一个字节为 0 (nul 终止符)。

CString&CStr 如同 String&str: 每对中的前者是拥有所有权的字符串; 后者是借用的。

创建一个 CString

CString 是从字节切片、字节 vector 或任何实现 Into<Vec<u8>> 创建的 (例如,您可以直接从 String&str,因为两者都实现了该 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 样式字符串 (由单个空字节终止的非空字节序列) ; 这些类型的字符串的主要用例是与类似 C 的代码进行互操作。 通常,您将需要转让该外部代码的所有权 to/from。 强烈建议您在使用 CString 之前通读 CString 文档,因为对 CString 实例的所有权管理不当会导致无效的内存访问,内存泄漏和其他内存错误。

Implementations§

source§

impl CString

1.0.0 · source

pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError>

从字节容器创建一个新的 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 字节的位置。

1.0.0 · source

pub unsafe fn from_vec_unchecked(v: Vec<u8>) -> Self

通过使用字节 vector 来创建 C 兼容字符串,而无需检查内部 0 字节。

该函数将追加尾随的 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
1.4.0 · source

pub unsafe fn from_raw(ptr: *mut c_char) -> CString

重新获得通过 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
1.4.0 · source

pub fn into_raw(self) -> *mut c_char

消耗 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.add(1) as u8);
    assert_eq!(b'o', *ptr.add(2) as u8);
    assert_eq!(b'\0', *ptr.add(3) as u8);

    // 重新获得指向空闲内存的指针
    let _ = CString::from_raw(ptr);
}
Run
1.7.0 · source

pub fn into_string(self) -> Result<String, IntoStringError>

如果 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
1.7.0 · source

pub fn into_bytes(self) -> Vec<u8>

消耗 CString 并返回底层的字节缓冲区。

返回的缓冲区不包含尾随 nul 终止符,并且保证不包含任何内部 nul 字节。

Examples
use std::ffi::CString;

let c_string = CString::new("foo").expect("CString::new failed");
let bytes = c_string.into_bytes();
assert_eq!(bytes, vec![b'f', b'o', b'o']);
Run
1.7.0 · source

pub fn into_bytes_with_nul(self) -> Vec<u8>

等效于 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
1.0.0 · source

pub fn as_bytes(&self) -> &[u8]

以字节片形式返回此 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
1.0.0 · source

pub fn as_bytes_with_nul(&self) -> &[u8]

等效于 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
1.20.0 · source

pub fn as_c_str(&self) -> &CStr

提取包含整个字符串的 CStr 切片。

Examples
use std::ffi::{CString, CStr};

let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
let cstr = c_string.as_c_str();
assert_eq!(cstr,
           CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
Run
1.20.0 · source

pub fn into_boxed_c_str(self) -> Box<CStr>

将此 CString 转换为 boxed CStr

Examples
use std::ffi::{CString, CStr};

let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
let boxed = c_string.into_boxed_c_str();
assert_eq!(&*boxed,
           CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
Run
1.58.0 · source

pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self

Vec<u8> 转换为 CString,而不检查给定的 Vec 上的不变量。

Safety

给定的 Vec 必须最后一个元素为一个 nul 字节。 这意味着它不能为空,也不能在其他任何地方有任何其他 nul 字节。

Example
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
1.58.0 · source

pub fn from_vec_with_nul(v: Vec<u8>) -> Result<Self, FromVecWithNulError>

尝试将 Vec<u8> 转换为 CString

存在运行时检查以确保 Vec (它的最后一个元素) 中只有一个 nul 字节。

Errors

如果存在 nul 字节而不是最后一个元素,或者不存在 nul 字节,则将返回错误。

Examples

如果调用成功而没有结尾的 nul 字节,则转换将产生与 CString::new 相同的结果。

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 会产生错误。

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>§

1.4.0 · source

pub fn to_string_lossy(&self) -> Cow<'_, str>

CStr 转换为 Cow<str>

如果 CStr 的内容是有效的 UTF-8 数据,该函数将返回一个 Cow::Borrowed(&str) 和相应的 &str 切片。 否则,它将用 U+FFFD 替换字符 替换任何无效的 UTF-8 序列,并返回 Cow::Owned(&str) 作为结果。

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
1.0.0 · source

pub fn as_ptr(&self) -> *const i8

返回此 C 字符串的内部指针。

返回的指针在 self 内一直有效,并且指向以 0 字节结尾的连续区域,以表示字符串的结尾。

返回指针的类型是 *const c_char,它是 *const i8 还是 *const u8 的别名是平台特定的。

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 返回的指针不携带任何生命周期信息,并且 CStringCString::new("Hello").expect("CString::new failed").as_ptr() 表达式计算后立即被释放。

要解决此问题,请将 CString 绑定到本地变量:

use std::ffi::CString;

let hello = CString::new("Hello").expect("CString::new failed");
let ptr = hello.as_ptr();
unsafe {
    // `ptr` 有效,因为 `hello` 在作用域内
    *ptr;
}
Run

这样,helloCString 的生命周期就包含了 ptrunsafe 区块的生命周期。

1.71.0 · source

pub fn is_empty(&self) -> bool

如果 self.to_bytes() 的长度为 0.

Examples
use std::ffi::CStr;

let cstr = CStr::from_bytes_with_nul(b"foo\0")?;
assert!(!cstr.is_empty());

let empty_cstr = CStr::from_bytes_with_nul(b"\0")?;
assert!(empty_cstr.is_empty());
Run
1.0.0 · source

pub fn to_bytes(&self) -> &[u8]

将此 C 字符串转换为字节片。

返回的切片将不包含此 C 字符串具有的尾随 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(), b"foo");
Run
1.0.0 · source

pub fn to_bytes_with_nul(&self) -> &[u8]

将此 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
1.4.0 · source

pub fn to_str(&self) -> Result<&str, Utf8Error>

如果 CStr 包含有效的 UTF-8,则产生 &str 切片。

如果 CStr 的内容是有效的 UTF-8 数据,该函数将返回相应的 &str 切片。

否则,它将返回错误,并详细说明 UTF-8 验证失败的位置。

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_str(), Ok("foo"));
Run

Trait Implementations§

1.7.0 · source§

impl AsRef<CStr> for CString

source§

fn as_ref(&self) -> &CStr

将此类型转换为 (通常是推断的) 输入类型的共享引用。
1.3.0 · source§

impl Borrow<CStr> for CString

source§

fn borrow(&self) -> &CStr

从拥有的值中一成不变地借用。 Read more
source§

impl Clone for CString

source§

fn clone(&self) -> CString

返回值的副本。 Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

source 执行复制分配。 Read more
1.0.0 · source§

impl Debug for CString

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

使用给定的格式化程序格式化该值。 Read more
1.10.0 · source§

impl Default for CString

source§

fn default() -> CString

创建一个空的 CString

1.0.0 · source§

impl Deref for CString

§

type Target = CStr

解引用后的结果类型。
source§

fn deref(&self) -> &CStr

解引用值。
1.13.0 · source§

impl Drop for CString

source§

fn drop(&mut self)

执行此类型的析构函数。 Read more
1.28.0 · source§

impl<'a> From<&'a CString> for Cow<'a, CStr>

source§

fn from(s: &'a CString) -> Cow<'a, CStr>

&CString 转换为借用的 Cow,无需复制或分配。

1.7.0 · source§

impl From<&CStr> for CString

source§

fn from(s: &CStr) -> CString

从输入类型转换为此类型。
1.18.0 · source§

impl From<Box<CStr, Global>> for CString

source§

fn from(s: Box<CStr>) -> CString

Box<CStr> 转换为 CString,无需复制或分配。

1.24.0 · source§

impl From<CString> for Arc<CStr>

source§

fn from(s: CString) -> Arc<CStr>

通过将 CString 数据移动到新的 Arc 缓冲区中,将 CString 转换为 Arc<CStr>

1.20.0 · source§

impl From<CString> for Box<CStr>

source§

fn from(s: CString) -> Box<CStr>

CString 转换为 Box<CStr>,无需复制或分配。

1.28.0 · source§

impl<'a> From<CString> for Cow<'a, CStr>

source§

fn from(s: CString) -> Cow<'a, CStr>

无需复制或分配即可将 CString 转换为拥有所有权的 Cow

1.24.0 · source§

impl From<CString> for Rc<CStr>

source§

fn from(s: CString) -> Rc<CStr>

通过将 CString 数据移动到新的 Arc 缓冲区中,将 CString 转换为 Rc<CStr>

1.7.0 · source§

impl From<CString> for Vec<u8>

source§

fn from(s: CString) -> Vec<u8>

CString 转换为 Vec<u8>

转换消耗 CString,并删除终止的 NUL 字节。

1.28.0 · source§

impl<'a> From<Cow<'a, CStr>> for CString

source§

fn from(s: Cow<'a, CStr>) -> Self

通过复制借用的内容将 Cow<'a, CStr> 转换为 CString

1.43.0 · source§

impl From<Vec<NonZeroU8, Global>> for CString

source§

fn from(v: Vec<NonZeroU8>) -> CString

Vec<NonZeroU8> 转换为 CString,无需复制或检查内部空字节。

source§

impl Hash for CString

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

将该值输入给定的 HasherRead more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)where H: Hasher, Self: Sized,

将这种类型的切片送入给定的 Hasher 中。 Read more
1.7.0 · source§

impl Index<RangeFull> for CString

§

type Output = CStr

索引后返回的类型。
source§

fn index(&self, _index: RangeFull) -> &CStr

执行索引 (container[index]) 操作。 Read more
source§

impl Ord for CString

source§

fn cmp(&self, other: &CString) -> Ordering

此方法返回 selfother 之间的 OrderingRead more
1.21.0 · source§

fn max(self, other: Self) -> Selfwhere Self: Sized,

比较并返回两个值中的最大值。 Read more
1.21.0 · source§

fn min(self, other: Self) -> Selfwhere Self: Sized,

比较并返回两个值中的最小值。 Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Selfwhere Self: Sized + PartialOrd<Self>,

将值限制在某个时间间隔内。 Read more
source§

impl PartialEq<CString> for CString

source§

fn eq(&self, other: &CString) -> bool

此方法测试 selfother 值是否相等,并由 == 使用。
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

此方法测试 !=。 默认实现几乎总是足够的,并且不应在没有充分理由的情况下被覆盖。
source§

impl PartialOrd<CString> for CString

source§

fn partial_cmp(&self, other: &CString) -> Option<Ordering>

如果存在,则此方法返回 selfother 值之间的顺序。 Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

此方法测试的内容少于 (对于 selfother),并且由 < 操作员使用。 Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

此方法测试小于或等于 (对于 selfother),并且由 <= 运算符使用。 Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

此方法测试大于 (对于 selfother),并且由 > 操作员使用。 Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

此方法测试是否大于或等于 (对于 selfother),并且由 >= 运算符使用。 Read more
source§

impl Eq for CString

source§

impl StructuralEq for CString

source§

impl StructuralPartialEq for CString

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

获取 selfTypeIdRead more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

从拥有的值中一成不变地借用。 Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

从拥有的值中借用。 Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

返回未更改的参数。

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

调用 U::from(self)

也就是说,这种转换是 From<T> for U 实现选择执行的任何操作。

source§

impl<T> ToOwned for Twhere T: Clone,

§

type Owned = T

获得所有权后的结果类型。
source§

fn to_owned(&self) -> T

从借用的数据创建拥有的数据,通常是通过克隆。 Read more
source§

fn clone_into(&self, target: &mut T)

使用借来的数据来替换拥有的数据,通常是通过克隆。 Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

发生转换错误时返回的类型。
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

执行转换。
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

发生转换错误时返回的类型。
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

执行转换。