C string FFI:有类似String :: from_raw_buf_with_max_len的东西

时间:2015-01-03 02:23:15

标签: string rust ffi

注意(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_maxlenString::from_array

1 个答案:

答案 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!");
    }
}