Now we're really making progress! I just realised that my wrapper dll actually works, when called from Rust, if not run in debug mode! If I start a Rust program using the debugger in VS Code the call to my wrapper returns scrap. If I just do cargo run then the returned value is valid!
I took my program down to the absolute basic (skipping bindgen and everything else non-related). The wrapper-version looks like this:
use std::ffi::CString;
#[allow(non_snake_case)]
extern "C" {
pub fn HiwinWrapper_GetVersion(pszVer: *mut ::std::os::raw::c_char);
}
fn main() {
println!("Hello, world!");
let mut array_u8: [u8;10] = [0;10];
unsafe {
HiwinWrapper_GetVersion(array_u8.as_mut_ptr().cast());
let valid = array_u8.split(|&b| b == 0).next().unwrap(); // handle error!
let string = CString::new(valid).unwrap(); // handle error!
if valid.is_ascii() {
let ascii = string.into_string().unwrap();
println!("{}",ascii);
} else {
println!("Returned string is not valid ASCII");
}
}
println!("\nGoodbye, world!");
}
If I swap my wrapper-dll for the real target Hiwin dll, giving the code below, then the call fails no matter if I run it with cargo run or from the debugger. (The link_name comes from the bindgen generated code, no clue what it's basing the name on?)
use std::ffi::CString;
#[allow(non_snake_case)]
extern "C" {
#[link_name = "\u{1}?MPI_GetVersion@@YAXPEAD@Z"]
pub fn MPI_GetVersion(pszVer: *mut ::std::os::raw::c_char);
}
fn main() {
println!("Hello, world!");
let mut array_u8: [u8;10] = [0;10];
unsafe {
MPI_GetVersion(array_u8.as_mut_ptr().cast());
let valid = array_u8.split(|&b| b == 0).next().unwrap(); // handle error!
let string = CString::new(valid).unwrap(); // handle error!
if valid.is_ascii() {
let ascii = string.into_string().unwrap();
println!("{}",ascii);
} else {
println!("Returned string is not valid ASCII");
}
}
println!("\nGoodbye, world!");
}
For now, my conclusion is that
- Rust cannot talk directly to stdcall-libraries
- Rust can talk to export "C" libraries
- The export "C" library works as expected in run-mode, but not in debug mode.
I can live with the fact that Rust cannot talk directly to stdcall-libraries. That is mentioned in other places and it's outside of my control. I think that this will be resolved sooner or later, but for now I can do with a workaround.
But the fact that my wrapper is bugging out when called from rust in debug mode, that feels like something that should be possible to mitigate? Is it something with my debug-settings in VS Code?
My VS Code settings are:
{
"version": "0.2.0",
"configurations": [
{
"name": "(Windows) Launch",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceRoot}/target/debug/RustHiwinTest.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"console": "externalTerminal"
}
]
}
/Henrik