Reputation: 4186
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.
Upvotes: 6
Views: 5442
Reputation: 91
There is also this kind of solution:
fn zascii(slice: &[c_char]) -> String {
String::from_iter(slice.iter().take_while(|c| **c != 0).map(|c| *c as u8 as char))
}
Upvotes: 2
Reputation: 313
you can create std::ffi::CStr from a pointer but you have to use unsafe keyword.Like this
use std::ffi::CStr;
//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:{:?}",unsafe{CStr::from_ptr(thing.id.as_ptr())}),
None => (),
}
}
you can also convert CStr into String by using this method
CStr::from_ptr(thing.id.as_ptr()).to_string_lossy()
Upvotes: 1
Reputation: 430604
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
.
Upvotes: 11