How to wrap `printf` in libc properly?


#1

I try to wrap printf just like the following code:

extern crate libc;
use libc::{c_char, c_int};

extern "C" {
    fn printf(fmt: *const c_char, ...) -> c_int;
}
fn main() {
    unsafe {
        printf("hello world\n".as_ptr() as *const i8);
    }
}

But it prints something really strange…


However, if I append extra \0 to string I want to print, it prints properly.

extern crate libc;
use libc::{c_char, c_int};

extern "C" {
    fn printf(fmt: *const c_char, ...) -> c_int;
}
fn main() {
    unsafe {
        printf("hello world\n\0".as_ptr() as *const i8);
    }
}

Is it a bug or I didn’t wrap the C function properly?


#2

C strings are zero-terminated. Rust strings are not. This is why the CStr and CString types exist.


#3

Thanks! :star_struck:


#4

Warning in advance - assing CString to a variable before calling as_ptr() on it. Temporary value (not assigned to a variable) will give invalid, crash-inducing pointer.


#5

assing CString

  • kornel, 2018

#6

I always like linking to your original post on the CString::as_ptr() issue.