简体   繁体   中英

How to convert char** to Vec<String> in rust

I have a rust static lib which is being linked int ac 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.

From the documentation :

Other usage (eg, 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);
    }
}

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
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM