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/