Sending and recieving numbers, strings, and window handles.
Tested with GameMaker Runtime Version 2.2.2.326.
In some examples, some dependencies may be omitted to brevity, but they can be seen in src/lib.rs.
In Cargo.toml
:
[lib]
crate-type = ["cdylib"]
// src/lib.rs
#[no_mangle]
pub extern "cdecl" fn foo(bar: f64) -> () {
println!("{:?}", bar);
}
Compile as 32bit DLL for compatibility with the 32bit YoYoGames runner:
$ cargo +stable-i686-pc-windows-gnu build --release
GameMaker script:
var foo = external_define("gamemaker_rust_dll_example.dll", "foo", dll_cdecl, ty_real, 1, ty_real);
external_call(foo, 123);
In Cargo.toml
:
[dependencies]
libc ="*"
extern crate libc;
use libc::c_char;
use std::ffi::CStr;
#[no_mangle]
pub extern "cdecl" fn bar(baz: *const c_char) -> () {
let c_str: &CStr = unsafe { CStr::from_ptr(baz) };
let str_slice: &str = c_str.to_str().unwrap();
println!("baz: {}", str_slice);
}
var bar = external_define("gamemaker_rust_dll_example.dll", "bar", dll_cdecl, ty_real, 1, ty_string);
external_call(bar, "baz");
In GameMaker, the result of window_handle()
must be cast into a (hex) ty_string
with string()
.
var print_window_handle = external_define("gamemaker_rust_dll_example.dll", "print_window_handle", dll_cdecl, ty_real, 1, ty_string);
external_call(print_window_handle, string(window_handle()));
In Rust, the hex string must be interpreted as a HWND
, which is basically an i64
. Although there is some nuance here that you can google for, such as the value will never exceed the maximum value of an i32
, or something along those lines.
use std::i64;
// ...
#[no_mangle]
pub extern "cdecl" fn print_window_handle(handle: *const c_char) -> () {
let c_str: &CStr = unsafe { CStr::from_ptr(handle) };
let hex_string: &str = c_str.to_str().unwrap();
let handle = i64::from_str_radix(hex_string, 16);
println!("HWND - HEX: {}, DEC: {:?}", hex_string, handle);
}
var foo_bar_baz = external_define(
"gamemaker_rust_dll_example.dll",
"foo_bar_baz",
dll_cdecl,
ty_string,
0
);
show_debug_message(external_call(foo_bar_baz)); // => foo bar baz
#[no_mangle]
pub extern "cdecl" fn foo_bar_baz() -> *const c_char {
let c_string = CString::new("foo bar baz").unwrap();
let pointer = c_string.into_raw();
pointer
}
var elite_number = external_define("gamemaker_rust_dll_example.dll", "elite_number", dll_cdecl, ty_real, 0);
show_debug_message(external_call(elite_number)); // => 1337
#[no_mangle]
pub extern "cdecl" fn elite_number() -> f64 {
1337.0f64
}