This is an example of how to make native extensions for GameMaker in Rust!
This lets you do
export! {
fn rust_get_string() -> GMStr {
rets("This string comes from Rust!")
}
fn rust_add_numbers(left: f64, right: f64) -> f64 {
left + right
}
}
instead of
#[unsafe(no_mangle)]
extern "C" fn rust_get_string() -> GMStr {
rets("This string comes from Rust!")
}
#[unsafe(no_mangle)]
extern "C" fn rust_add_numbers(left: f64, right: f64) -> f64 {
left + right
}
similar to how I always have a dllx
"decorator" in my C++ extensions.
This one's easy, you specify f64
for argument types and/or return type and that's it.
This one's quirkier due to FFI philosophy differences between languages -
Rust generally expects (CString.into_raw
) the returned C strings to be free
d
by the caller program while GM makes a copy of the returned string without free
ing it.
This means that you must store the string you're about to return somewhere
so that it does not get free
d on function exit.
For this reason I'm including gm::gets
(create a Rust String
from a GM string)
and gm::rets
(convert a Rust &str
to a GM string for immediate return) helper functions.
On GM side you mark the argument as a "string" (pointer, really),
pass a buffer_get_address
to the native extension,
and that's it! This is an actual pointer to buffer data so you can also write to the buffer,
but note that you'll need to call buffer_set_used_size
afterwards if you're populating
a freshly made buffer with data.
Compile a DyLib/SO and add it as a separate Proxy File to the extension using the GameMaker IDE.
I don't have a functioning Mac to test this.