I have tried stepping it forward adding piece by piece.
I start with just these lines:
unsafe {
let mut array: [std::os::raw::c_char;10] = [33;10];
hiwinInterface::MPI_GetVersion(array.as_mut_ptr());
}
It compiles fine and when I debug it I can see the expected value on the array in the variables-view.
I add the following line at the bottom of the unsafe clause:
let array_u8: [u8;10] = std::mem::transmute(array.to_owned());
I can now see the correct value in the array_u8 array as well.
I add the below.
let version = CString::new(array_u8);
Now, when I debug the code, I can see the array being filled with the correct string, then the array_u8 gets the string. Finally a new field shows up in the Variables-window, but it's not called "version" as I would have expected, but "alloc::ffi::c_str::CString::new<array$<u8,10> > returned: Err".
After some digging I found that the problem is that we got a 0 in the middle of the array!
According to documentation for CString there must be no null-terminations within the array when creating a CString. But what if there is?? I would like to get a string from the array that ends where the array is null-terminated. I have tried to parse the array in a couple of ways, but I havn't found anything that does the trick.
I tried to validate each value before adding it to a vector like this:
let mut array_u8: [u8;10];
unsafe {
let mut array: [std::os::raw::c_char;10] = [33;10];
hiwinInterface::MPI_GetVersion(array.as_mut_ptr());
array_u8 = std::mem::transmute(array.to_owned().clone());
}
let mut vers = Vec::new();
for char in array_u8 {
if char == 0{
break;
}
if char < 46 || char > 57 { // Sanity check, I expect nothing but numbers and points.
return Err(HiwinError::DriverVersion);
}
vers.push(char);
}
But then the returned value from MPI_GetVersion turns into junk again. The parsing quickly finds a character that is not a number or point, so the function returns with error.
The only thing I have found so far that doesn't destroy the returned value from MPI_GetVersion is to simply copy the values one by one like this:
let mut array_u8: [u8;10];
unsafe {
let mut array: [std::os::raw::c_char;10] = [33;10];
hiwinInterface::MPI_GetVersion(array.as_mut_ptr());
array_u8 = std::mem::transmute(array.to_owned().clone());
}
let major = array_u8[0];
let minor = array_u8[2];
let patch = array_u8[4];
let build = array_u8[6];
This works and I get the expected value, but it assumes a format on the string from the DLL, which is outside of my control.
Is there a way I can print the string, as is, without destroying it?