如何在 Rust 中将 char** 转换为 Vec<String>

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

我有一个 rust 静态库,它正在链接到一个 c 项目。在大多数情况下,它运行良好。但是我不知道如何将 c char* 数组传递给 rust 并将其转换为 rust Vec。

我的C代码:

int rust_main(int argc, char** argv);

int main(int argc, char **argv)
{
    rust_main(argc, argv);
    return 0;
}

我的 Rust 代码:

#[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);
    }
}

代码编译正常,但是当我尝试访问字符串指针数组时,我得到一个核心转储。

如果有人能指出我正确的方向,将不胜感激。

来自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.

您应该调用 CStr::from_ptr,然后根据需要使用 to_strto_string_lossyinto_c_string 转换为自有值。

#[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);
    }
}

C代码不能共享slice(真的没办法)

我试图举一个例子,将 argv 转换为 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
    }
}