String C字符串FFI:是否有类似字符串::from_raw_buf_和_max_len的东西

String C字符串FFI:是否有类似字符串::from_raw_buf_和_max_len的东西,string,rust,ffi,String,Rust,Ffi,注意(2015年5月):这个问题是关于Rust语言在稳定和1.0发布之前的问题,现在主要是历史问题:代码不会在稳定的Rust上编译,等等 我正在为我正在从事的一个项目编写一个libpcap包装器,并学习Rust(我刚刚开始做)。我现在正在写一本关于这件事的安全书: #[link(name = "pcap")] extern { fn pcap_lookupdev(errormsg: *mut libc::c_char) -> *const libc::c_char; } 以下是

注意(2015年5月):这个问题是关于Rust语言在稳定和1.0发布之前的问题,现在主要是历史问题:代码不会在稳定的Rust上编译,等等


我正在为我正在从事的一个项目编写一个libpcap包装器,并学习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) })
    }
}
fn lookupdev()->结果{
//容量必须至少为PCAP\u ERRBUF\u大小
让mut errbuf=[0作为c_字符,…256];
让结果=不安全{
让ptr=pcap_lookupdev(errbuf.as_mut_ptr()as*mut libc::c_char);
如果ptr.is_null(){
没有一个
}
否则{
一些(CString::new(ptr,false))
}
};
比赛结果{
Some(result)=>Ok(result.as_str().unwrap().to_string()),
None=>Err(不安全的{String::from_raw_buf(errbuf.as_ptr()as*const u8)})
}
}
这是可行的,但我不喜欢使用from
String::from_raw_buf
,它将愉快地遍历千兆字节的内存,而不是在到达errbuf末尾时停止

我可以手动编写循环
errbuf
,并将其转换为Rust字符串(在缓冲区末尾停止),但在我看来,这是Rust标准库应该支持的字符串的C FFI习惯用法(传递分配的内存块,其中可以写入字符串)。然而,我在Rust FFI指南和标准图书馆文档中都找不到任何内容


处理这个生锈的FFI案件的最好方法是什么?是否至少有一个
String::from_raw_buf_with_maxlen
或一个
String::from_array

Rust标准库本身似乎无法处理这种可能性:

这可能是无意的,在我看来,一个bug应该与锈迹一起归档

所以我认为现在没有一个简单的解决办法。我能想到的就是这个

#![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!");
    }
}

这正是我想知道的。包括对现有锈代码的引用,以显示所做的工作是非常棒的。非常感谢。稍后我将对这个bug进行评论。