Reputation: 544
I have a rust static lib which is being linked int a c project. For the most part it is working well. However I can't figure out how to pass an array of c char* into rust and have it convert to a rust Vec.
My C code:
int rust_main(int argc, char** argv);
int main(int argc, char **argv)
{
rust_main(argc, argv);
return 0;
}
My Rust Code:
#[no_mangle]
pub unsafe extern "C" fn rust_main(argc : c_int , argv : &[*mut c_char]) -> c_int {
let arglen = argc as usize;
println!("Args: {}", argc);
for x in 0..arglen {
let var = CString::from_raw(argv[x]);
let printable = var.to_string_lossy();
println!("{}", x);
}
}
Code compiles fine however when I try to access the string pointer array I get a Core Dump.
If anyone could point me in the right direction it would be much appreciated.
Upvotes: 3
Views: 1514
Reputation: 26717
You can't share slice with C code (There is really no way).
I tried to make an example that could make sense to convert argv to String
.
use libc::{c_char, size_t, c_int};
use std::ffi::CStr;
use std::slice::from_raw_parts;
use std::str::Utf8Error;
pub unsafe fn convert_double_pointer_to_vec(
data: &mut &mut c_char,
len: size_t,
) -> Result<Vec<String>, Utf8Error> {
from_raw_parts(data, len)
.iter()
.map(|arg| CStr::from_ptr(*arg).to_str().map(ToString::to_string))
.collect()
}
#[no_mangle]
pub unsafe extern "C" fn rust_main(argc : c_int , data: &mut &mut c_char) -> c_int {
let argv = convert_double_pointer_to_vec(data, argc as size_t);
if let Ok(mut argv) = argv {
for (i, arg) in argv.iter_mut().enumerate() {
arg.insert_str(0, &format!("{}: ", i));
}
println!("{:#?}", argv);
0
}
else {
1
}
}
Upvotes: 3
Reputation: 10872
From the documentation:
Other usage (e.g., trying to take ownership of a string that was allocated by foreign code) is likely to lead to undefined behavior or allocator corruption.
Note: If you need to borrow a string that was allocated by foreign code, use CStr.
You should be calling CStr::from_ptr
and then convert to an owned value with either to_str
, to_string_lossy
or into_c_string
as needed.
#[no_mangle]
pub unsafe extern "C" fn rust_main(argc : c_int , argv : &[*mut c_char]) -> c_int {
let arglen = argc as usize;
println!("Args: {}", argc);
for x in 0..arglen {
let var = CStr::from_ptr(argv[x]);
let printable = var.to_string_lossy();
println!("{}", x);
}
}
Upvotes: 2