Reputation: 57
I've been trying to call a Rust function from C with multiple string arguments, but for some reason the only argument that being sent is the first. This is what I've tried:
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);
}
}
Upvotes: 1
Views: 632
Reputation: 57
C code:
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);
}
Rust code:
#[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);
}
}
Upvotes: -1
Reputation: 42302
First, the code you provide is straight up broken, the C snippet makes absolutely no sense.
Second, your types are completely mismatched.
&str
is a Rust type, C has no equivalent builtin type, and it most certainly is not equivalent to a C string, its low-level payload (the underlying buffer) is not even compatible with C strings because Rust strings are not nul-terminated. The compiler literally tells you that:
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
Furthermore, from the C side you're sending a char
not even a C string.
So what you're doing here is sending two characters, telling Rust that they're really two rust strings, and then misusing that as two C strings, your code has as many UBs as it has lines.
The Rust function should be taking *mut c_char
, and the C extern
should be defined as taking two char*
.
Upvotes: 3