通过Rust FFI更改C数组元素

通过Rust FFI更改C数组元素,rust,ffi,Rust,Ffi,我正在使用Rust测试一些C代码: lol.c #包括“lol.h” INTA[10]//假设lol.h有[10]的外部声明 lib.rs extern "C" { static a: *mut i32; } fn set_a(val: i32, index: usize) { assert!(index < 10); unsafe { a[index] = val; } } fn get_a(index: usize) { a

我正在使用Rust测试一些C代码:

lol.c

#包括“lol.h”
INTA[10]//假设lol.h有[10]的外部声明
lib.rs

extern "C" {
    static a: *mut i32;
}

fn set_a(val: i32, index: usize) {
    assert!(index < 10);
    unsafe {
        a[index] = val;
    }
}

fn get_a(index: usize) {
    assert!(index < 10);
    unsafe { a[index] }
}
使用:

像这样:

extern crate libc;

use libc::malloc;
use std::mem::size_of;

unsafe fn zero(data: *mut u32, length: usize) {
    for i in 0..length - 1 {
        let ptr = data.offset(i as isize) as *mut u32;
        *ptr = 0;
    }
}

unsafe fn set(data: *mut u32, offset: usize, value: u32) {
    let ptr = data.offset(offset as isize) as *mut u32;
    *ptr = value;
}

unsafe fn get(data: *mut u32, offset: usize) -> u32 {
    let ptr = data.offset(offset as isize) as *mut u32;
    return *ptr;
}

unsafe fn alloc(length: usize) -> *mut u32 {
    let raw = malloc(length * size_of::<*mut u32>());
    return raw as *mut u32;
}

fn main() {
    unsafe {
        let data = alloc(10);
        zero(data, 10);

        println!("{:?}", get(data, 4));

        set(data, 4, 100);
        println!("{:?}", get(data, 4));
    }
}
extern板条箱libc;
使用libc::malloc;
使用std::mem::size\u;
不安全fn零(数据:*mut u32,长度:usize){
对于0..length-1中的i{
设ptr=data.offset(i为isize)为*mut u32;
*ptr=0;
}
}
不安全fn集合(数据:*mut u32,偏移量:usize,值:u32){
设ptr=data.offset(偏移量为isize)为*mut u32;
*ptr=值;
}
不安全的fn get(数据:*mut u32,偏移量:usize)->u32{
设ptr=data.offset(偏移量为isize)为*mut u32;
返回*ptr;
}
不安全fn alloc(长度:usize)->*mut u32{
设raw=malloc(长度*大小::());
返回原始值为*mut u32;
}
fn main(){
不安全{
设数据=alloc(10);
零(数据,10);
println!(“{:?}”,get(data,4));
集合(数据,4100);
println!(“{:?}”,get(data,4));
}
}
您可以使用该方法查找单个元素,或者使用从指针和(可能是动态的)长度创建切片,或者首先使用
静态mut a:*mut[i32;10]
(使用
(*a)[index]
使用它)

但是:我很确定
inta[10]
from
C
不会导出指向该数组的指针的位置,它会导出数组的位置(即第一个元素的位置),而
extern
在Rust中会将位置导出为给定类型的值(即,它在两侧都实现为指针),因此我会尝试以下方法:

extern "C" {
    static mut a: [i32; 10];
}

fn set_a(val: i32, index: usize) {
    unsafe {
        a[index] = val;
    }
}

fn get_a(index: usize) -> i32 {
    unsafe { a[index] }
}

旁白:C的锈当量
int
不是
i32
;它在板条箱里。这正是我想要的。工作得很好我有两个问题?使用isize是因为C索引不同于Rust吗?还有你为什么要去马洛克。空间已经在C中分配了,对吗?@KDN malloc只是一个例子(上面的代码在play.rust-lang.org上运行)。显然,在你的情况下,没有必要这样做。usize是因为在C语言中使用x[-1]是合法的(有时也是有意义的);所以offset()可以取-ve数字。在本例中,允许-ve值是没有意义的,因此我将其设为usize而不是isize,但这是任意的。如果你不在乎,就用isize。
extern "C" {
    static mut a: [i32; 10];
}

fn set_a(val: i32, index: usize) {
    unsafe {
        a[index] = val;
    }
}

fn get_a(index: usize) -> i32 {
    unsafe { a[index] }
}