注意(2015年5月):这个问题是关于Rust语言在它稳定并且1.0发布之前,现在主要是历史兴趣:代码不能在稳定的Rust等上编译。
我正在为liblcap编写一个包装器,用于我正在研究的项目,并学习Rust(我刚刚开始做)。我正在努力为此写一个安全的Rust:
#[link(name = "pcap")]
extern {
fn pcap_lookupdev(errormsg: *mut libc::c_char) -> *const libc::c_char;
}
这是我到目前为止所得到的:
fn lookupdev() -> Result<String, String> {
// Capacity must be at least PCAP_ERRBUF_SIZE
let mut errbuf = [0 as c_char, ..256];
let result = unsafe {
let ptr = pcap_lookupdev(errbuf.as_mut_ptr() as *mut libc::c_char);
if ptr.is_null() {
None
}
else {
Some(CString::new(ptr, false))
}
};
match result {
Some(result) => Ok(result.as_str().unwrap().to_string()),
None => Err(unsafe { String::from_raw_buf(errbuf.as_ptr() as *const u8) })
}
}
这样可行,但我不喜欢String::from_raw_buf
的使用,它会愉快地遍历千兆字节的内存而不是在到达errbuf结束时停止。
我可以手动编写一些循环遍历errbuf
并将其转换为Rust字符串(在缓冲区末尾停止)的东西,但在我看来这是字符串的C FFI习语(传递一个已分配的块)可以由Rust标准库支持的内存(可以写入字符串)。但是,我无法在Rust FFI指南或标准库文档中找到任何内容。
在Rust中处理此FFI案例的最佳方法是什么?是否至少有String::from_raw_buf_with_maxlen
或String::from_array
?
答案 0 :(得分:3)
Rust标准库本身似乎并没有真正处理这种可能性:
这可能是无意的,IMO,一个臭虫应该提交给Rust。
所以我认为现在没有一个简单的解决方案。我能想出的就是这个
#![feature(slicing_syntax)]
extern crate libc;
use std::c_str::CString;
fn main() {
let errbuf = ['o' as libc::c_char; 256];
if errbuf.iter().any(|c| *c == 0 as libc::c_char) {
unsafe { CString::new(errbuf.as_ptr(), false).to_string() };
} else {
panic!("FFI returned invalid string!");
}
}