我正在围绕C库编写一个Rust包装器。 C库提供以下功能:

void lib_foo(const unsigned char *buf, uint32_t buf_len);

我创建了以下extern包装器:

fn lib_foo(buf: *const u8, buf_len: u32);

和以下高级包装器:

pub fn foo(buf: &[u8]) {
    unsafe { lib_foo(buf.as_ptr(), buf.len() as u32) }
}

但是,从usize(buf.len()的类型)到u32的转换可能会导致大小被截断。处理此问题的最佳方法是什么?

最佳答案

首先,请使用 libc crate 输入类型。

即:extern fn lib_foo(buf: *const libc::c_uchar, buf_len: libc::uint32_t);
虽然稍长一些,但可以避免做出假设(unsigned char映射到u8)并使翻译自动进行。

然后,进入高级包装器。

在没有任何假设的情况下,最简单的解决方案是 panic 并记录下来。

/// Calls `lib_foo`, ...
///
/// # Panics
///
/// If the size of the buffer is strictly greater than 2^32-1 bytes.
pub fn foo(buf: &[u8]) {
    assert!(buf.len() <= (std::u32::MAX as usize));

    unsafe { lib_foo(buf.as_ptr() as *const _, buf.len() as libc::uint32_t) }
}

然后,根据域,可能会出现其他选择:
  • 饱和度可能是一个选项(使用std::cmp::min)
  • 重复调用可能是另一个
  • ...

  • 在任何情况下,如果用户可以观察到行为差异,请记录文档。

    关于c - 如何处理将usize传递给期望uint32_t的C函数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40255192/

    10-10 04:34