简体   繁体   English

如何将Rust`Args`转换为argc和argv C等价物?

[英]How do I convert Rust `Args` into the argc and argv C equivalents?

I am using a C API (in particular MPI_Init ) that needs int argc, char **argv . 我正在使用需要int argc, char **argv的C API(特别是MPI_Init )。 I am trying to generate an equivalent argc, argv with the following code: 我正在尝试使用以下代码生成等效的argc, argv

let argc = std::env::args().len() as c_int;
let c_strs: ~[CString] = std::env:args().map(|s: & &str| s.to_c_str());
let mut argv: ~[*c_char] = c_strs.map(|c: &CString| c.with_ref(|ptr| ptr));
if null_terminate {
    argv.push(std::ptr::null());
}

By adapting this discussion on Github . 通过在Github上调整此讨论

It fails with: 它失败了:

error: expected type, found `~`
src/lib.rs:37   let c_strs: ~[CString] = std::env::args().map(|s: & &str| s.to_c_str());
                            ^

I got rid of the ~ and then it could not find to_c_str() and was unsure what to replace to_c_str with, to_raw() (for instance) failed. 我摆脱了~然后它找不到to_c_str()并且不确定要替换to_c_strto_raw() (例如)失败。

Does anyone know of a way to convert Args to a more C friendly format? 有没有人知道如何将Args转换为更友好的C格式?

My answer works with the current stable Rust (1.5) and probably with beta and nightly. 我的答案适用于目前稳定的Rust(1.5),可能还有beta和nightly。

The following Rust code calls the foo(argc, argv) function implemented in C. The signature of foo is very similar to a main function. 下面锈病代码调用foo(argc, argv)中C.实施的功能的签名foo是非常类似于一个main功能。

extern crate libc;

use libc::c_char;
use libc::c_int;

use std::ffi::CString;

#[link(name="foo")]
extern "C" {
    fn foo(argc: c_int, argv: *const *const c_char);
}

fn main() {
    // create a vector of zero terminated strings
    let args = std::env::args().map(|arg| CString::new(arg).unwrap() ).collect::<Vec<CString>>();
    // convert the strings to raw pointers
    let c_args = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<*const c_char>>();
    unsafe {
        // pass the pointer of the vector's internal buffer to a C function
        foo(c_args.len() as c_int, c_args.as_ptr());
    };
}

Note, that the C side only borrows the pointers to the strings. 注意,C端只借用指向字符串的指针。 If you want to store them, use strdup() on them. 如果要存储它们,请在它们上使用strdup()

I also used unwrap() on CString instances. 我还在CString实例上使用了unwrap() If your string contains 0 bytes, it will return an error, see https://doc.rust-lang.org/stable/std/ffi/struct.CString.html#method.new . 如果您的字符串包含0个字节,则会返回错误,请参阅https://doc.rust-lang.org/stable/std/ffi/struct.CString.html#method.new

Proof: 证明:

I put this code into a cargo project, and added libc as a dependency. 我将此代码放入货物项目中,并将libc添加为依赖项。 The foo() function looks like this: foo()函数如下所示:

#include <stdio.h>

void foo(int argc, char* argv[]) {
    int i;

    for (i = 0; i < argc; i++) {
        printf("argv[%d]: %s\n", i, argv[i]);
    }
}

I compiled this code with: 我编译了这段代码:

gcc foo.c -o libfoo.so -shared -fPIC

Then copied libfoo.so under target/debug/deps (just to be in the library search path). 然后在target/debug/deps下复制libfoo.so (只是在库搜索路径中)。 Then I run my cargo project: 然后我运行我的货物项目:

$ cargo run the quick brown fox
   Compiling args v0.1.0 (file:///home/tibi/Codes/Rust/argv/args)
     Running `target/debug/args the quick brown fox`
argv[0]: target/debug/args
argv[1]: the
argv[2]: quick
argv[3]: brown
argv[4]: fox

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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