[英]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_str
, to_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.