Search code examples
rustffi

Change C array element via Rust FFI


I'm using Rust to test some C code:

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

I used the cc crate to compile and link lol.o. How do I write the set_a and get_a functions? The compiler says:

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] }
   |              ^^^^^^^^

Solution

  • You could use the offset method to find a single element, or use std::slice::from_raw_parts_mut to create a slice from pointer and (possibly dynamic) length, or use static mut a: *mut [i32; 10] in the first place (use (*a)[index] to use it).

    But: I'm pretty sure that int a[10]; from C doesn't export a location of a pointer to that array, it exports the location of the array (i.e the location of the first element), and extern in Rust expects a location to a value of the given type (i.e. it is implemented as a pointer on both sides) , so I'd try this:

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