TUTORIAL / 04
Call Haxe from Rust
Paint a picture with a Haxe function and let callback exceptions reach the caller.
1. Pass a Haxe function
The picture example lets Rust call a Haxe function for each pixel. Here is the Rust method and a Haxe caller:
pub fn paint<E>(&mut self, shade: impl Fn(i32, i32) -> Result<i32, E>) -> Result<(), E> {
for y in 0..self.height {
for x in 0..self.width {
let level = shade(x, y)?.clamp(0, 255);
self.pixels[(y * self.width + x) as usize] = level as u8;
}
}
Ok(())
}
var disc = new Picture(25, 9);
disc.paint((x, y) -> {
var dx = x - 12, dy = (y - 4) * 2;
return dx * dx + dy * dy <= 36 ? 255 : 0;
});
The callback runs during paint, on the calling Haxe thread. Rust uses ? to stop painting when it fails.
2. Throw from the callback
try {
disc.paint((x, y) -> {
if (x == 5)
throw new haxe.Exception('gave up at column $x');
return 0;
});
} catch (error:haxe.Exception) {
Sys.println(error.message);
}
The original Haxe exception reaches the caller of paint after Rust returns. Return Result<T, E> from Rust callback signatures and propagate Err; hxn handles the exception conversion.
3. Borrow objects and return bytes
var line = new Picture(25, 9);
line.paint((x, y) -> y == 4 ? 255 : 0);
// One object is passed as a parameter to another object's method.
disc.lighten(line);
pub fn pixels(&self) -> Vec<u8> {
self.pixels.clone()
}
lighten(&mut self, other: &Picture) borrows the second picture for the call. Both Haxe objects remain usable. Vec<u8> becomes haxe.io.Bytes; use pixels.get(index) to read it. Call close() to release a picture promptly; otherwise its finalizer releases it.
Run the example
From the repository root, run the complete example:
cd examples/picture
hxn run hl
Full Rust and Haxe source ↗ · Use hxn run cpp for hxcpp.