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)
该memset和memcpy的东西很容易解决。我假定的边界检查是通过以下方式实现的libcore-在不链接到libcore的情况下以任何方式使其正常工作?(无论如何这可能都是合理的事情...)
而不是强制转换缓冲区,而是对缓冲区强制转换引用。例
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配合使用?它是标准库的子集,涵盖不需要操作系统支持的所有内容。您可以通过它获得字符串操作函数。