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

使用类型“[my_struct]”是将C结构数组传递给Rust函数的正确方法吗?,c,struct,rust,ffi,C,Struct,Rust,Ffi,C文件: typedef结构点{ int x; int-y; }点; typedef结构点{ 整数计数; 点*点的数组; }点数; 锈迹文件: #[派生(调试)] #[报告员(C)] 发布结构点{ x:c_int, y:c_int, } #[导出(调试)] #[报告员(C)] 发布结构点{ 计数:c_int, _点的数组_:[点], } #[没有损坏] pub fn do_something(所有积分:&积分){ 对于0中的i..all_points.count{ 设crr_point=&所有

C文件:

typedef结构点{
int x;
int-y;
}点;
typedef结构点{
整数计数;
点*点的数组;
}点数;
锈迹文件:

#[派生(调试)]
#[报告员(C)]
发布结构点{
x:c_int,
y:c_int,
}
#[导出(调试)]
#[报告员(C)]
发布结构点{
计数:c_int,
_点的数组_:[点],
}
#[没有损坏]
pub fn do_something(所有积分:&积分){
对于0中的i..all_points.count{
设crr_point=&所有_points.array_of_points[i as usize];
println!(“{:?}”,crr_点);
}
}
在我的C文件中,我分配了很多结构点,并将它们添加到点的数组中,然后调用
do\u something
函数

如何获取锈迹中的
点阵列中的每个点

我用Rust定义点的
数组的方法正确吗

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

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

以此类推。

这是未定义的行为。在该类型的生锈版本中,点
类型的点
的成员数组被转换为未生锈的切片,该切片既不等效也不兼容。通过添加类型为
[point]
的成员,您建议
point
在其第一个成员
count
之后有一个数量可变的尾部
point
对象。这也使得
成为未调整大小的类型(或动态调整大小的类型)

C中
点的内存布局应如下所示:

[int,point*]
|
-->[点,点,…]//动态分配
但锈的定义是这样的:

[int,point,point,…]//未知的编译时大小
点中的成员需要使用原始指针定义:

#[derive(Debug)]
#[repr(C)]
pub struct points {
    count: c_int,
    array_of_points: *mut point,
}
然后,
dou\u 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);
        }
    }
}
或在
点中的给定零件上制作一个适当的锈片

#[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);
    }
}
请注意,在这些情况下,您是如何需要
不安全的
代码的

另见:


这是未定义的行为。在该类型的生锈版本中,类型为
point*
的点的成员
数组\u被转换为生锈的无尺寸切片
[point]
,该切片既不等效也不兼容。通过添加类型为
[point]
的成员,您建议
point
在其第一个成员
count
之后有一个数量可变的尾部
point
对象。这也使得
成为未调整大小的类型(或动态调整大小的类型)

C中
点的内存布局应如下所示:

[int,point*]
|
-->[点,点,…]//动态分配
但锈的定义是这样的:

[int,point,point,…]//未知的编译时大小
点中的成员需要使用原始指针定义:

#[derive(Debug)]
#[repr(C)]
pub struct points {
    count: c_int,
    array_of_points: *mut point,
}
然后,
dou\u 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);
        }
    }
}
或在
点中的给定零件上制作一个适当的锈片

#[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);
    }
}
请注意,在这些情况下,您是如何需要
不安全的
代码的

另见:

注意:这个答案有点离题,它建议您为C代码使用另一种数据布局

您可以将C结构更改为以下内容:

typedef结构点{
int x;
int-y;
}点;
typedef结构点{
尺寸透镜;
点数[];
}点数;
这就是所谓的a,一个非常好而且未知的C特性,它只允许您进行一次分配。典型用例与您的用例相匹配

此外,即使在C
int
中,int也不是表示大小的合适类型,您也应该使用
size\u t

您还应该使用来处理FAM,它提供了有用的函数,如
as\u slice()

给定以下C代码:

typedef结构点{
int x;
int-y;
}点;
typedef结构点{
尺寸透镜;
点数[];
}点数;
结构点*新点(尺寸长度){
结构点*points=malloc(sizeof*points+sizeof*points->points*len);
如果(点数){
点->透镜=透镜;
}
返回点;
}
它目前生成:

#[repr(C)]
#[衍生(默认)]
pub-struct_u_不完全数组字段(::std::marker::PhantomData);
impl\uuu不完全数组字段{
#[内联]
pub fn new()->Self{
__不完全数组字段(::std::marker::PhantomData)
}
#[内联]
发布不安全fn as_ptr(&self)->*常数{
::std::mem::transmute(self)
}
#[内联]
发布不安全的fn as_mut_ptr(&mut self)->*mut T T{
::std::mem::transmute(self)
}
#[内联]
发布不安全fn as_切片(&self,len:usize)->和[T]{
::std::slice::from_raw_parts(self.as_ptr(),len)
}
#[内联]
发布不安全的fn作为多个切片(&mut self,len:usize)->&mut[T]{
::std::slice::from_raw_parts_mut(self.as_mut_ptr(),len)
}
}
impl::std::fmt::调试不完全数组字段{
fn fmt(&self,fmt:&mut::std::fmt::Formatter注意:这个答案有点错误,它建议您为您的C代码使用另一个数据布局

您可以将C结构更改为以下内容:

typedef结构点{
int x;
int-y;
}点;
typedef结构点{
尺寸透镜;
点数[];
}要点;
这就是所谓的a,一个非常好的未知的C特性,它只允许您进行一次分配

还有,伊芙