extern functions

Extern functions are declared in Mun but their function bodies are defined externally. They behave exactly the same as regular functions but their definitions have to be provided to the runtime when loading a Mun library. Failure to do so will result in a runtime link error, and loading the library will fail. Take this code for example:

extern fn random() -> i64;

pub fn random_bool() -> bool {
    random() % 2 == 0
}

Listing 2-1: Random bool in Mun

The random function is marked as an extern function, which means that it must be provided to the runtime when loading this library.

First building the above code as main.munlib and then trying to load the library in Rust using:

extern crate mun_runtime;
use mun_runtime::Runtime;

fn main() {
    // Safety: We assume that the library that is loaded is a valid munlib
    let builder = Runtime::builder("main.munlib");
    let mut runtime = unsafe { builder.finish() }.expect("Failed to spawn Runtime");

    let result: bool = runtime.invoke("random_bool", ()).unwrap();
    println!("random bool: {}", result);
}

Listing 2-2: Load listing 2-1 without adding extern function

will result in an error:

Failed to link: function `random` is missing.

This indicates that we have to provide the runtime with the random method, which we can do through the use of the insert_fn method. Let's add a method that uses the current time as the base of our random method:

extern crate mun_runtime;
use mun_runtime::Runtime;

extern "C" fn random() -> i64 {
    let result = std::time::Instant::now().elapsed().subsec_nanos() as i64;
    println!("random: {}", result);
    result
}

fn main() {
    // Safety: We assume that the library that is loaded is a valid munlib
    let builder =
        Runtime::builder("main.munlib").insert_fn("random", random as extern "C" fn() -> i64);
    let mut runtime = unsafe { builder.finish() }.expect("Failed to spawn Runtime");

    let result: bool = runtime.invoke("random_bool", ()).unwrap();
    println!("random_bool: {}", result);
}

Listing 2-3: Load listing 2-1 with custom random function

Note that we have to explicitly cast the function random to extern "C" fn() -> i64. This is because each function in Rust has its own unique type.

When we run this now, the error is gone and you should have a function that returns a random boolean in Mun.