简体   繁体   中英

Convert “*mut *mut f32” into “&[&[f32]]”

I want to convert arrays.

Example:

func()-> *mut *mut f32;
...
let buffer = func();
for n in 0..48000 {
    buffer[0][n] = 1.0;
    buffer[1][n] = 3.0;
}

In Rust &[T] / &mut [T] is called a slice. A slice is not an array; it is a pointer to the beginning of an array and the number of items in this array. Therefore, to create &mut [T] out of *mut T , you need to known the length of the array behind the pointer.

*mut *mut T looks like a C implementation of a 2D, possibly jagged, array, ie an array of arrays (this is different from a contiguous 2D array, as you probably know). There is no free way to convert it to &mut [&mut [T]] , because, as I said before, *mut T is one pointer-sized number, while &mut [T] is two pointer-sized numbers. So you can't, for example, transmute *mut T to &mut [T] , it would be a size mismatch. Therefore, you can't simply transform *mut *mut f32 to &mut [&mut [f32]] because of the layout mismatch.

In order to safely work with numbers stored in *mut *mut f32 , you need, first, determine the length of the outer array and lengths of all of the inner arrays. For simplicity, let's consider that they are all known statically:

const ROWS: usize = 48000;
const COLUMNS: usize = 48000;

Now, since you know the length, you can convert the outer pointer to a slice of raw pointers:

use std::slice;

let buffer: *mut *mut f32 = func();

let buf_slice: &mut [*mut f32] = unsafe {
    slice::from_raw_parts_mut(buffer, ROWS);
};

Now you need to go through this slice and convert each item to a slice, collecting the results into a vector:

let matrix: Vec<&mut [f32]> = buf_slice.iter_mut()
    .map(|p| unsafe { slice::from_raw_parts_mut(p, COLUMNS) })
    .collect();

And now you can indeed access your buffer by indices:

for n in 0..COLUMNS {
    matrix[0][n] = 1.0;
    matrix[1][n] = 3.0;
}

(I have put explicit types on bindings for readability, most of them in fact can be omitted)

So, there are two main things to consider when converting raw pointers to slices:

  1. you need to know exact length of the array to create a slice from it; if you know it, you can use slice::from_raw_parts() or slice::from_raw_parts_mut() ;
  2. if you are converting nested arrays, you need to rebuild each layer of the indirection because pointers have different size than slices.

And naturally, you have to track who is the owner of the buffer and when it will be freed, otherwise you can easily get a slice pointing to a buffer which does not exist anymore. This is unsafe , after all.

Since your array seems to be an array of pointers to an array of 48000 f32 s, you can simply use fixed size arrays ( [T; N] ) instead of slices ( [T] ):

fn func() -> *mut *mut f32 { unimplemented!() }

fn main() {
    let buffer = func();
    let buffer: &mut [&mut [f32; 48000]; 2] = unsafe { std::mem::transmute(buffer) };
    for n in 0..48000 {
        buffer[0][n] = 1.0;
        buffer[1][n] = 3.0;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM