问题描述
我一直在尝试使用多个字符串参数从 C 调用 Rust 函数,但由于某种原因,唯一发送的参数是第一个。这是我试过的:
input.c
extern void print_str(char str1,char str2);
void c_function() {
scanf("%s %s",str1,str2);
print_str(str1,str2);
}
lib.rs:
#[no_mangle]
pub extern "C" fn print_str(str1: &str,str2: &str) {
unsafe {
libc::printf(str1.as_ptr() as *const libc::c_char);
libc::printf(str2.as_ptr() as *const libc::c_char);
}
}
解决方法
首先,您提供的代码直接被破坏了,C 代码段完全没有意义。
其次,您的类型完全不匹配。
&str
是 Rust 类型,C 没有等效的内置类型,而且它肯定不等效于 C 字符串,它的低级有效负载(底层缓冲区)甚至与 C 字符串不兼容,因为Rust 字符串不是以 null 结尾的。编译器字面上告诉你:
warning: `extern` fn uses type `str`,which is not FFI-safe
--> src/lib.rs:2:35
|
2 | pub extern "C" fn print_str(str1: &str,str2: &str) {
| ^^^^ not FFI-safe
|
= note: `#[warn(improper_ctypes_definitions)]` on by default
= help: consider using `*const u8` and a length instead
= note: string slices have no C equivalent
此外,从 C 端发送的 char
甚至不是 C 字符串。
所以你在这里做的是发送两个字符,告诉 Rust 它们实际上是两个 rust 字符串,然后将 that 误用为两个 C 字符串,你的代码有和它一样多的 UB有线条。
Rust 函数应该取 *mut c_char
,而 C extern
应该定义为取两个 char*
。
C 代码:
extern void print_str(char *str1,char *str2);
void c_function() {
char str1[10];
char str2[10];
scanf("%s "%s",str1,str2);
print_str(str1,str2);
}
锈代码:
#[no_mangle]
pub extern "C" fn print_str(str1: &str,str2: &str) {
unsafe {
libc::printf(str1.as_ptr() as *const c_char);
libc::printf(str2.as_ptr() as *const c_char);
}
}