如何在Rust中索引C数组?

8

我有一个返回指针的C函数:

type MYSQL_RES_REF = *mut c_void;
type MYSQL_ROW = *const *const c_char;

#[no_mangle]
extern "C" {
    fn mysql_fetch_row(res: MYSQL_RES_REF) -> MYSQL_ROW;
}

let pointer = mysql_fetch_row(self.res);
let row_p = match pointer {
    p if p == (0 as *const *const c_char) => panic!(),
    p => p,
};

let field: &[u8] = unsafe { ffi::c_str_to_bytes(row_p[i]) };

但是尝试对它进行索引(最后一行)会导致错误:
error: cannot index a value of type `*const *const i8`

我想知道std::c_vec是否是我想要的,但是显然已经被移除了


2
请注意,这不是一个数组,在C语言中不要混淆指针和数组,它们并不相同。 - Stargateur
2个回答

15

指针上有一个offset方法,可以这样使用:

let new_p = p.offset(i);

获取指向距当前位置 i 个元素的指针。这明显没有进行边界检查,因此你必须确保它在范围内(或者是超出末尾一个元素)。


还有一个不稳定的 offset 内建函数


自 Rust 1.26.0 起,还有无符号偏移量的方法 add(),以及用于无符号负偏移量的 sub() 方法。 - Chayim Friedman

3
如果你有C数组的长度,你可以将指针和长度转换为Rust切片,然后使用现有的所有切片支持。
use libc::size_t; // 0.2.51
use std::slice;

/// Our opaque C type
#[repr(C)]
struct MyCType {
    private: [u8; 0],
}

extern "C" {
    fn get_ptr_and_len(len: *mut size_t) -> *const MyCType;
    fn do_something_with_type(v: *const MyCType);
}

fn ptr_and_len() {
    unsafe {
        let mut len = 0;
        let ptr = get_ptr_and_len(&mut len);

        let slice = slice::from_raw_parts(ptr, len);

        // Indexing
        do_something_with_type(&slice[42]);

        // Iteration
        for v in slice {
            do_something_with_type(v);
        }
    }
}

另请参阅:


让mut len = 0;没有意义,因为它的值应该被get_ptr_and_len()替换,如果函数返回一个错误,那么len就是无意义的,或者函数出现故障,所以初始化仍然无用。然而,这并不会造成太大损失,但是在函数被频繁使用的情况下,可能会造成影响。那么如何告诉Rust len将被初始化呢?由于它只是一个整数,这应该很简单。我认为。 - Stargateur
另外,C语言不能有private: [u8; 0],字段,因此这可能是一个不好的例子。 - Stargateur
@Stargateur 这就是如何创建一个不透明类型(因此链接)。 - Shepmaster
@Stargateur,无法指定FFI代码将初始化长度的方法。在纯Rust中,您将返回一组值的元组,但是在FFI中不可能实现。您可以使用mem :: uninitialized,但对于可以轻松归零的类型来说,这太过浪费了。 - Shepmaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接