I am completely new to rust but have prior experience in C and I have this rust code which does not compile.
use std::fs;
static mut GRAPH_BUILDER: Option<Box<[&[u8]; 2]>> = None;
#[export_name = "wizer.initialize"]
pub extern "C" fn init() {
let weights = fs::read("./mobilenet.bin").unwrap();
let xml = fs::read_to_string("./mobilenet.xml").unwrap().into_bytes();
let input: [&[u8]; 2] = [&weights, &xml];
unsafe {
GRAPH_BUILDER = Some(Box::new(input));
}
}
pub fn main() {
unsafe {
if GRAPH_BUILDER.is_none() {
init();
}
}
}
When compiled with rustc main.rs
It produces these errors
error[E0597]: `weights` does not live long enough
--> main.rs:9:30
|
9 | let input: [&[u8]; 2] = [&weights, &xml];
| ^^^^^^^^ borrowed value does not live long enough
...
12 | GRAPH_BUILDER = Some(Box::new(input));
| --------------- argument requires that `weights` is borrowed for `'static`
13 | }
14 | }
| - `weights` dropped here while still borrowed
error[E0597]: `xml` does not live long enough
--> main.rs:9:40
|
9 | let input: [&[u8]; 2] = [&weights, &xml];
| ^^^^ borrowed value does not live long enough
...
12 | GRAPH_BUILDER = Some(Box::new(input));
| --------------- argument requires that `xml` is borrowed for `'static`
13 | }
14 | }
| - `xml` dropped here while still borrowed
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0597`.
I understand that this error is caused because weights
is stored on the stack and will be unallocated when the init
function terminates, so the static GRAPH_BUILDER
would contain a pointer to unallocated memory. So I tried to use a Box
instead, which from my understanding should act like malloc in C. But it does not seem to work. How can I get rust to allocate the weights
and xml
variables on the heap, without knowing their sizes at compile time? I.e. What is the rust-equivalent of malloc?
I have read here that you can call clone
to fix this problem. But I don't want to do it because the files I read in are large. And I also don't understand why that would fix the problem. Wouldn't the clone just end up on the stack too?
EDIT: Another important thing I should mention, I need to provide GRAPH_BUILDER
as an argument to the wasi_nn::load function, and it essentially expects it to be of the datatype slice &[&[u8]]
. But I have absolutely no idea how to convert it to this datatype. Here is the continuation of the main function.
use wasi_nn;
pub extern "C" fn main() {
bench::start();
let context: wasi_nn::GraphExecutionContext;
unsafe {
if GRAPH_BUILDER.is_none() {
init();
}
}
let graph = unsafe {
wasi_nn::load(
&GRAPH_BUILDER.expect("Graph builder was not initialized"),
wasi_nn::GRAPH_ENCODING_OPENVINO,
wasi_nn::EXECUTION_TARGET_CPU,
)
.unwrap()
};
I am trying to modify this code such that it creates &[&xml.into_bytes(), &weights]
in an initialization function instead of passing it directly.