首页 文章

通过Rust FFI更改C数组元素[重复]

提问于
浏览
-1

这个问题在这里已有答案:

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

lol.c

#include "lol.h"
int a[10]; //Assume lol.h has an extern declaration for a[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] }
}

我使用the cc crate来编译和链接lol.o.如何编写 set_aget_a 函数?编译器说:

error[E0608]: cannot index into a value of type `*mut i32`
 --> src/main.rs:8:9
  |
8 |         a[index] = val;
  |         ^^^^^^^^

error[E0608]: cannot index into a value of type `*mut i32`
  --> src/main.rs:14:14
   |
14 |     unsafe { a[index] }
   |              ^^^^^^^^

2 回答

  • 2

    您可以使用offset方法查找单个元素,或使用std::slice::from_raw_parts_mut从指针创建切片和(可能是动态的)长度,或者首先使用 static mut a: *mut [i32; 10] (使用 (*a)[index] 来使用它) .

    但是:我很确定来自 Cint a[10]; 不会导出指向该数组的指针位置,它会导出数组的位置(即第一个元素的位置),并且Rust中的 extern 需要一个位置给定类型的值(即它实现为两边的指针),所以我试试这个:

    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] }
    }
    
  • 1

    使用:

    a.offset(x) as *mut i32
    

    像这样:

    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));
        }
    }
    

相关问题