Marshalling Structs
When embedding Mun in other languages, you will probably want to retrieve, modify and send structures across the boundary - of the two languages. When this so-called marshalling occurs, there is often an associated performance penalty because the Mun Runtime needs to perform runtime checks to validate the provided data types.
Mun provides a homogeneous interface for marshalling any struct through a StructRef
- a reference to a heap-allocated struct.
The Mun Runtime automatically handles the conversion from a function return type into a StructRef
and function arguments into Mun structs.
For structs with the
gc
memory kind, marshalling reuses the memory allocated by the garbage collector, but for structs with thevalue
memory kind this requires their value to be copied into heap memory.
Listing 4-11 shows how to marshal Vector2
instances from Mun to Rust and vice versa, using the vector2_new
and vector2_add
functions - previously defined.
extern crate mun_runtime;
use mun_runtime::{Runtime, StructRef};
use std::env;
fn main() {
let lib_path = env::args().nth(1).expect("Expected path to a Mun library.");
// Safety: We assume that the library that is loaded is a valid munlib
let builder = Runtime::builder(lib_path);
let mut runtime = unsafe { builder.finish() }
.expect("Failed to spawn Runtime");
let a: StructRef = runtime.invoke("vector2_new", (-1.0f32, 1.0f32)).unwrap();
let b: StructRef = runtime.invoke("vector2_new", (1.0f32, -1.0f32)).unwrap();
let added: StructRef = runtime.invoke("vector2_add", (a, b)).unwrap();
}
Accessing Fields
The API of StructRef
consists of three generic methods for accessing fields: get
, set
, and replace
; respectively for retrieving, modifying, and replacing a struct field.
The desired field is specified using a string field_name
parameter, which is identical to the one used with the dot notation in Mun code.
extern crate mun_runtime;
use mun_runtime::{Runtime, StructRef};
use std::env;
fn main() {
let lib_path = env::args().nth(1).expect("Expected path to a Mun library.");
// Safety: We assume that the library that is loaded is a valid munlib
let builder = Runtime::builder(lib_path);
let mut runtime = unsafe { builder.finish() }
.expect("Failed to spawn Runtime");
let mut xy: StructRef = runtime.invoke("vector2_new", (-1.0f32, 1.0f32)).unwrap();
let x: f32 = xy.get("x").unwrap();
xy.set("x", x * x).unwrap();
let y = xy.replace("y", -1.0f32).unwrap();
}