Search code examples
rustffi

Convert from a fixed-sized c_char array to CString


My FFI binding returns a struct with fixed-size c_char arrays, and I would like to turn those into std::ffi::CString or std::String.

It looks like the CString::new function coerces the pointer to a vector.

use std::ffi::CString;
use std::os::raw::c_char;

#[repr(C)]
pub struct FFIStruct {
    pub Id: [::std::os::raw::c_char; 256usize],
    pub Description: [::std::os::raw::c_char; 256usize],
}

fn get_struct() -> Option<FFIStruct> {
    println!("cheating");
    None
}

pub fn main() {
    match get_struct() {
        Some(thing) => 
            println!("Got id:{}",CString::new(thing.Id.as_ptr())),

        None => (),
    }
}

Here is the Rust Playground link.


Solution

  • C strings that you don't own should be translated using CStr, not CString. You can then convert it into an owned representation (CString) or convert it into a String:

    extern crate libc;
    
    use libc::c_char;
    use std::ffi::CStr;
    
    pub fn main() {
        let id = [0 as c_char; 256];
        let rust_id = unsafe { CStr::from_ptr(id.as_ptr()) };
        let rust_id = rust_id.to_owned();
        println!("{:?}", rust_id);
    }
    

    You should also use the libc crate for types like c_char.