Struct std::ffi::CString1.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 并返回基础的字节缓冲区。

返回的缓冲区不包含尾随 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

等效于 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

提取包含整个字符串的 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

将此 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
🔬 This is a nightly-only experimental API. (cstring_from_vec_with_nul #73179)

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
🔬 This is a nightly-only experimental API. (cstring_from_vec_with_nul #73179)

尝试将 Vec<u8> 转换为 CString

存在运行时检查以确保 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

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

将此 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

将此 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 切片。

如果 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

CStr 转换为 Cow<str>

如果 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

执行转换。

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

返回值的副本。 Read more

source 执行复制分配。 Read more

使用给定的格式化程序格式化该值。 Read more

创建一个空的 CString

解引用后的结果类型。

解引用值。

执行此类型的析构函数。 Read more

执行转换。

执行转换。

无需复制或分配即可将 Box<CStr> 转换为 CString

CString 转换为 Vec<u8>

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

无需复制或分配即可将 CString 转换为 Box<CStr>

执行转换。

无需复制或分配即可将 CString 转换为 Arc<CStr>

无需复制或分配即可将 CString 转换为 Rc<CStr>

执行转换。

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

将该值输入给定的 HasherRead more

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

索引后返回的类型。

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

此方法返回 selfother 之间的 OrderingRead more

比较并返回两个值中的最大值。 Read more

比较并返回两个值中的最小值。 Read more

将值限制为一定的时间间隔。 Read more

此方法测试 selfother 值是否相等,并由 == 使用。 Read more

此方法测试 !=

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

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

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

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

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

Auto Trait Implementations

Blanket Implementations

获取 selfTypeIdRead more

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

从拥有的值中借用。 Read more

执行转换。

执行转换。

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

通常通过克隆从借用数据中创建拥有的数据。 Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into #41263)

recently added

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

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

执行转换。

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

执行转换。