如何在没有libstd和libcore的情况下从&str转换为* const i8 *?

Per*_*erg 1 string operating-system kernel rust

我的场景是大约15年前有一个用C编写的现有(旧)操作系统。现在,我们正在考虑扩展该系统,使其能够在Rust中编写用户空间程序。

自然,因为这是最近才开始的,所以我们还没有为将其全部移植libstd到我们自己的操作系统而烦恼。因此,我们正在使用#![feature(no_std)]

现在,我正在寻找应该相当简单的东西:将Rust字符串转换为C-null终止的string。应该很简单,但是由于我对Rust缺乏经验,所以我(尚未)能够弄清楚。

为了获得这种经验,足以施加某些限制(例如,最大1024个字节长的字符串;其他所有内容都将被截断)。(我们确实有适当的内存分配,但是我还没有为尝试从Rust处理内存分配而烦恼)

到目前为止,这是我微不足道的尝试:

pub struct CString {
    buffer: [i8; 1024]
}

impl CString {
    pub fn new(s: &str) -> CString {
        CString {
            buffer: CString::to_c_string(s)
        }
    }

    fn to_c_string(s: &str) -> [i8; 1024] {
        let buffer: [i8; 1024];
        let mut i = 0;

        // TODO: ignore the risk for buffer overruns for now. :)
        // TODO: likewise with UTF8; assume that we are ASCII-only.
        for c in s.chars() {
            buffer[i] = c as i8;
            i = i + 1;
        }

        buffer[s.len()] = '\0' as i8;
        buffer;
    }

    pub fn as_ptr(&self) -> *const i8 {    
        // TODO: Implement. The line below doesn't even compile.
        self.buffer as *const i8
    }
}
Run Code Online (Sandbox Code Playgroud)

这里的核心问题是中的类型转换as_ptr。您如何在Rust中进行操作?另外,除了明显的问题之外,此代码还有其他问题吗?(UTF8非ASCII字符处理中断,如果字符串长于1024个字符,则完全是愚蠢的... :)

提前非常感谢!这一定是相当明显的。。。


更新:根据威尔·菲舍尔的回答(谢谢!),我将as_ptr方法更改为如下所示:

pub fn as_ptr(&self) -> *const i8 {
    &self.buffer as *const i8
}
Run Code Online (Sandbox Code Playgroud)

该代码现在可以编译,但是不会链接:

virtio_net_pci.0.rs:(.text._ZN6system8c_string7CString3new20hbfc6c6db748de66bpaaE+0x31): undefined reference to `memset'
virtio_net_pci.0.rs:(.text._ZN6system8c_string7CString3new20hbfc6c6db748de66bpaaE+0x14f): undefined reference to `memcpy'
virtio_net_pci.0.rs:(.text._ZN6system8c_string7CString3new20hbfc6c6db748de66bpaaE+0x174): undefined reference to `panicking::panic_bounds_check::h0b7be17a72a754b5P6E'
virtio_net_pci.0.rs:(.text._ZN6system8c_string7CString3new20hbfc6c6db748de66bpaaE+0x18c): undefined reference to `panicking::panic_bounds_check::h0b7be17a72a754b5P6E'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

memsetmemcpy的东西很容易解决。我假定的边界检查是通过以下方式实现的libcore-在不链接到libcore的情况下以任何方式使其正常工作?(无论如何这可能都是合理的事情...)

Wil*_*her 5

而不是强制转换缓冲区,而是对缓冲区强制转换引用。

fn main() {
    let buffer: [i8; 1024] = [42; 1024];
    let ptr: *const i8 = &buffer as *const i8;
    unsafe {
        println!("{}", *ptr.offset(30));
    }
}
Run Code Online (Sandbox Code Playgroud)

您是否尝试过将代码与libcore配合使用?它是标准库的子集,涵盖不需要操作系统支持的所有内容。您可以通过它获得字符串操作函数。

  • 重要说明:由于as_ptr消耗了self,因此可以编译代码,但是返回值将是悬空的指针。 (3认同)