简体   繁体   English

将“* mut * mut f32”转换为“&[&[f32]]”

[英]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. 在Rust &[T] / &mut [T]中称为切片。 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 [T] out *mut T ,您需要知道指针后面的数组的长度。

*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). *mut *mut T看起来像一个2D,可能是锯齿状的数组的C实现,即一个数组数组(这与连续的2D数组不同,你可能知道)。 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. 没有自由的方法将它转换为&mut [&mut [T]] ,因为正如我之前所说, *mut T是一个指针大小的数字,而&mut [T]是两个指针大小的数字。 So you can't, for example, transmute *mut T to &mut [T] , it would be a size mismatch. 所以你不能,例如,将*mut T&mut [T] ,这将是一个大小不匹配。 Therefore, you can't simply transform *mut *mut f32 to &mut [&mut [f32]] because of the layout mismatch. 因此,由于布局不匹配,您无法简单地将*mut *mut f32&mut [&mut [f32]]

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. 为了安全地处理存储在*mut *mut f32 ,首先需要确定外部数组的长度和所有内部数组的长度。 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() ; 如果您知道,可以使用slice::from_raw_parts()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. 毕竟,这是unsafe

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] ): 由于您的数组似乎是一个指向48000 f32 s数组的指针数组,因此您只需使用固定大小的数组( [T; N] )而不是切片( [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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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