通过Rust FFI更改C数组元素

时间:2018-02-07 06:31:03

标签: rust ffi

我正在使用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 个答案:

答案 0 :(得分:2)

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

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

extern

答案 1 :(得分: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));
    }
}