Reputation: 41
I'm trying to use Rust with C, by creating DLL and connect it to my C-project. And now, I have some troubles with passing pointers.
I wrote some example and tried to understand this problem:
#[no_mangle]
pub extern fn hex2ascii(hex_len : usize, hex_in: *const u8, ascii_len : &mut usize, ascii_out : *mut c_char) -> *mut c_char {
let mut out_str = String::new();
unsafe {
let array = std::slice::from_raw_parts(hex_in, hex_len);
for i in array
{
out_str.push_str(&(format!("0x{:02X?}, ", i)));
}
println!("{ }", out_str);
out_str.pop();
*ascii_len = out_str.len();
ascii_out = std::ffi::CString::new(out_str.clone()).unwrap().into_raw();
return ascii_out;
}
}
If I try to replace return ascii_out;
with return std::ffi::CString::new(out_str.clone()).unwrap().into_raw();
, it will work properly. But I want to put pointer in ascii_out and read it in my C-proj.
P.S. Adding a simple test on C++
unsigned char arr[] = { 0x32, 0x45, 0xab, 0xFF, 0x00, 0x3C };
size_t size = 0;
int size2 = sizeof(arr);
char *out = hex2ascii(size2, arr, &size);
for (int i = 0; i < size - 1; i++)
{
std::cout << out[i];
}
std::cout << std::endl;
However, I want to have something like this:
unsigned char arr[] = { 0x32, 0x45, 0xab, 0xFF, 0x00, 0x3C };
size_t size = 0;
int size2 = sizeof(arr);
char out[255]; // here can be any size
int rc = hex2ascii(size2, arr, &size, out);
for (int i = 0; i < size - 1; i++)
{
std::cout << out[i];
}
std::cout << std::endl;
Upvotes: 3
Views: 571
Reputation: 952
If you got everything to build and link properly the solution you're looking for is inside of std::ptr::copy. It will copy N bytes from source to destination.
"std::ptr::copy is semantically equivalent to C's memmove, but with the argument order swapped."
If you've stumbled across this post, and haven't got linking or compilation to work - I recommend looking at this github repo
Somewhat of a side note - if you know memory isn't overlapping it's recommended to use std::ptr::copy_nonoverlapping
instead.
use std::ffi::CString;
use std::os::raw::c_char;
#[no_mangle]
pub extern "C" fn hex2ascii(
hex_in: *const u8,
hex_len : usize,
ascii_len : &mut usize,
ascii_out : *mut c_char
) -> *mut c_char
{
let mut out_str = String::new();
unsafe {
let array = std::slice::from_raw_parts(hex_in, hex_len);
for i in array {
out_str.push_str(&(format!("0x{:02X?}, ", i)));
}
out_str.pop();
*ascii_len = out_str.len();
let c_str_out = CString::new(out_str).unwrap();
std::ptr::copy(c_str_out.as_ptr(), ascii_out, *ascii_len); // Copy N bytes to dst from src
return c_str_out.into_raw();
}
}
// note I changed the parameter order in rust.
// this code reflects those changes.
int main() {
unsigned char arr[] = { 0x32, 0x45, 0xab, 0xFF, 0x00, 0x3C };
size_t size = 0;
int size2 = sizeof(arr);
char out[255]; // here can be any size
char * old_way = hex2ascii(arr, size2, &size, out);
for (int i = 0; i < size - 1; i++)
{
std::cout << out[i];
}
std::cout << std::endl;
}
Upvotes: 2