c - 使用类型 `[my_struct]` 是将 C 结构数组传递给 Rust 函数的正确方法吗?

标签 c struct rust ffi

C 文件:

typedef struct point {
    int x;
    int y;
} point;

typedef struct points {
    int count;
    point *array_of_points;
} points;

使用rust 文件:

#[derive(Debug)]
#[repr(C)]
pub struct point {
    x: c_int,
    y: c_int,
}

#[derive(Debug)]
#[repr(C)]
pub struct points {
    count: c_int,
    array_of_points: [point],
}

#[no_mangle]
pub fn do_something(all_points: &points) {
    for i in 0..all_points.count {
        let crr_point = &all_points.array_of_points[i as usize];
        println!("{:?}", crr_point);
    }
}

在我的 C 文件中,我分配了很多结构点并将它们添加到 array_of_points,然后我调用了 do_something 函数。

我如何在 Rust 中获取 array_of_points 中的每个单点?

我在 Rust 中定义 array_of_points 数组的方式是否正确?

当我运行它时,出现了这个奇怪的结果:

point { x: 0, y: -952095696 }   
point { x: 32674, y: 101 }   

等等。

最佳答案

这是未定义的行为。在该类型的 Rust 版本中,成员 array_of_points , 类型 point* , 被翻译成一个 Rust unsized slice [point] ,既不等价也不兼容。通过添加 [point] 类型的成员, 你是在暗示 point有可变数量的尾随 point在其第一个成员之后直接对象 count .这也使得 points未调整大小的类型(或动态调整大小的类型)。

points的内存布局在 C 中应该是以下内容:

[ int, point* ]
           |
            -->[ point, point, ...] // dynamically allocated

但是 Rust 的定义是这样的:

[ int, point, point, ... ]          // unknown compile time size

points中的成员需要用原始指针定义:

#[derive(Debug)]
#[repr(C)]
pub struct points {
    count: c_int,
    array_of_points: *mut point,
}

然后do_something应该通过偏移量取消引用指针以检索每个点:

#[no_mangle]
pub fn do_something(all_points: &points) {
    for i in 0..all_points.count {
        unsafe {
            let crr_point = &*all_points.array_of_points.offset(i as isize);
            println!("{:?}", crr_point);
        }
    }
}

或者从 points 中的给定部分构造一个合适的 Rust 切片:

#[no_mangle]
pub fn do_something(all_points: &points) {
    let point_array = unsafe {
        std::slice::from_raw_parts(all_points.array_of_points, all_points.count as usize)
    };
    for crr_point in point_array {
        println!("{:?}", crr_point);
    }
}

记下您需要的方式unsafe任何这些情况下的代码。

另见:

关于c - 使用类型 `[my_struct]` 是将 C 结构数组传递给 Rust 函数的正确方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53050214/

相关文章:

Rust:有没有办法使用 map 缩短这个 if/else 代码?

rust - 两次通过闭包而没有被移走

rust - 如何生成静态链接的可执行文件?

c++ - 关于struct data 'getting'的性能

C:向动态分配的数组添加元素

C 嵌套开关 : outer switch's case inside inner switch

Golang 嵌入式结构类型

arrays - 在 Golang 中创建此 JSON 对象的最佳方法

c - 汇编消息 : Error: attempt to move . org 向后

c - 在 C 中一般地传递​​参数