I'm using windows api in my project and I start a thread for some usage.
I want to pass my clap handled parameters (which is Vec<String> ) to *const c_void.
The length of Vec can only be known in runtime and the length of it won't change.
I use the code below,but I'm not sure about whether I can directly transform slice to *const c_void
unsafe {
// cli.params are Vec<String>
let param : Vec<*const c_void> = cli.params.into_iter().map(|x| CString::new(x).expect("failed to convert String to CString").into_raw() as _).collect();
let param = param.as_slice();
// Can &[*const c_void] convert to **const c_void?
let handle = CreateThread(None, 0, std::mem::transmute(load_file("/path/to/file")?), Some(param.as_ptr() as *const _), 0, None)?;
WaitForSingleObject(handle,INFINITE);
}
Am I doing right here?if not,please help me to correctly transform it.
**const c_void is not a Rust type but *consr *const c_void and *mut *const c_void are. You can convert it to the former but not the latter (well, you can technically convert it to both, but actually writing to the latter will be UB).
You'll probably want to be using a CString type which guarantees having the same layout as that of a char * in C (*const/mut c_char in Rust), such as:
Indeed, using such a type simplifies things quite a bit (otherwise you'll need twoVecs, one for the owned CStrings, and one having .iter().map(|cstr| cstr.as_ptr()).collect::<Vec<_>>()):
use ::safer_ffi::prelude::*;
let params: Vec<char_p::Box> = cli.params.into_iter().map(|s| char_p::new(s)).collect();
let params_ptr: *const char_p::Box = params.as_ptr();
let params_void_ptr: *const *const c_void = params_ptr.cast();
unsafe {
let handle = CreateThread(None, 0, …, Some(params_void_ptr), 0, None)?;
WaitForSingleObject(handle, INFINITE);
}
The easiest solution is to push a nullptr to the Vec/chain a iter::once(nullptr()) so the thread can get the number of arguments from that.
The transmute to LPTHREAD_START_ROUTINE::Some looks very fishy to me. What is the signature of load_file? Is the function written in rust or some external C code? Do you control it?