我使用的是C API(特别MPI_Init
)需要int argc, char **argv
。我正在尝试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());
}
通过适应在Github上的讨论。
它失败并显示:
error: expected type, found `~`
src/lib.rs:37 let c_strs: ~[CString] = std::env::args().map(|s: & &str| s.to_c_str());
^
我摆脱了~
,然后就再也找不到to_c_str()
和不确定什么来代替to_c_str
用,to_raw()
(例如)失败。
有谁知道一种转换Args
为更友好的C格式的方法吗?
我的答案适用于当前稳定的Rust(1.5),可能适用于beta版本和夜间版本。
以下Rust代码调用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());
};
}
请注意,C侧仅借用了指向字符串的指针。如果要存储它们,请strdup()
在它们上使用。
我也用unwrap()
在CString
实例上。如果您的字符串包含0个字节,它将返回错误,请参阅https://doc.rust-lang.org/stable/std/ffi/struct.CString.html#method.new。
证明:
我将此代码放入了一个货运项目,并添加libc
为依赖项。该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]);
}
}
我用以下代码编译了这段代码:
gcc foo.c -o libfoo.so -shared -fPIC
然后复制到libfoo.so
下target/debug/deps
(仅在库搜索路径中)。然后我运行我的货运项目:
$ 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
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句