Предупреждение: я сам новичок в Rust; Я просто работаю над той же самой проблемой и, таким образом, немного узнал о ней. Могут быть лучшие решения или альтернативы тому, что я предложил здесь.
Если в C у вас есть указатель на массив
uint8_t *data;
, который инициализируется malloc
и ожидается, что его время жизни будет таким же, как и у содержащей его структуры, то в Rust вы пишете не data: &u8
, а:
data: Box<[u8]>,
Это отличается от вашей попытки двумя способами:
- Он имеет
[u8]
вместо u8
, поэтому он хранит много элементов вместо одного. - Он имеет
Box<...>
вместо &...
, поэтому ему принадлежит то, что он ссылается на.
Создание бокса размещает его содержимое в куче и, таким образом, напрямую соответствует использованию malloc
. Здесь я изменил ваш код, чтобы показать, как это работает, а также позаботился обо всех предупреждениях:
struct Map {
width: usize,
height: usize,
data: Box<[u8]>,
}
fn load_map() -> Map {
const W: usize = 8;
const H: usize = 8;
//allocate the map data
let data = [0;W*H];
// create the map structure
let m = Map {
width: W,
height: H,
data: Box::new(data)
};
m
}
fn main() {
let m: Map = load_map();
println!("Hello, world! {} {} {}", m.height, m.width, m.data[0]);
}
Обратите внимание, что явные параметры времени жизни <'a>
и 'static
исчезли; они сейчас не нужны, и они бы не работали (потому что что-то, выделенное функцией , не может быть 'static
, если вы не выберете утечку это).
Однако для этого по-прежнему требуется const
ширина и высота, чтобы построить массив, который не будет работать, как только ширина и высота будут считаны из файла карты. Чтобы исправить это, вам нужно построить массив (или, точнее, срез массива) другим способом; один из вариантов - использовать конструктор Vec
(а затем упростить его до фрагмента массива, потому что вы не планируете изменять длину):
data: vec![0; w * h].into_boxed_slice(),