【问题标题】:How do I convert a &str to a *const u8? [duplicate]如何将 &str 转换为 *const u8? [复制]
【发布时间】:2018-03-09 23:14:35
【问题描述】:

我有一个函数

extern "C" {
    fn log_impl(ptr: *const u8);
}

fn log(s: &str) {
    log_impl(s.as_bytes() as *const u8);
}

这给了我以下错误:

error[E0606]: casting `&[u8]` as `*const u8` is invalid
 --> src/main.rs:6:14
  |
6 |     log_impl(s.as_bytes() as *const u8);
  |              ^^^^^^^^^^^^^^^^^^^^^^^^^

与我正在尝试做的最相似的问题是 Converting a str to a &[u8].

【问题讨论】:

标签: rust


【解决方案1】:

Rust 字符串不像大多数 C 函数所期望的那样以 NUL 结尾。您可以使用&s.as_bytes()[0] as *const u8s.as_ptr()&str 转换为*const u8,但这对于传递给任何期望以NUL 结尾的字符串的C 函数是无效的。

相反,您可能需要使用 CString 将字符串复制到缓冲区并在末尾添加 NUL 终止符。这是一个假设 log_impl 不存储指向字符串的指针的示例:

fn log(s: &str) {
    unsafe {
        let c_str = CString::new(s).unwrap();
        log_impl(c_str.as_ptr() as *const u8);
    }
}

【讨论】:

  • 这个函数可能不需要标记为unsafe,而应该在内部使用unsafe块。
  • 我同意。我只是这样做,因为它使示例更短,并且仍然可以复制并粘贴到 Rust 游乐场。我对其进行了编辑以添加不安全的块。
  • 作为一个生锈的菜鸟问:假设&str最初来自一些String,我们可以用s.push("\0")预加载原始String吗?这会起作用还是我错过了什么?
  • @JaySullivan 是的,如果 String 具有 0 字节的容量而无需重新分配,那么这样做会比使用 CString 更有效。 CString 只做两件事:检查字符串中间是否没有 0 字节,并在末尾添加一个 0 字节(这意味着它通常必须复制整个字符串)。
  • 为了避免不必要的堆分配,而不是CString,我使用a function I wrote 检查&str 是否已经以\0 结尾,如果是,则按原样使用它,如果它足够小,则退回到将其复制到堆栈中,然后退回到将其复制到堆中(堆栈与堆由 SmallVec 库处理)。
【解决方案2】:

&[u8] 在 Rust 中称为切片,*u8 是原始指针。您可以使用from_ptr()as_ptr() 在这两种类型之间来回切换。

extern "C" {
    fn log_impl(ptr: *const u8);
}

fn log(s: &str) {
    log_impl(s.as_bytes().as_ptr() as *const u8);
}

【讨论】:

    猜你喜欢
    • 2015-09-26
    • 2021-05-14
    • 2017-02-09
    • 2021-05-26
    • 2020-06-06
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多