'How do I get a *mut c_char from a Str?
To be able to use C library, I need to give a *mut c_char
parameter to a function. But I don't find a way to have it from a str
.
I converted my str to a CString, that's ok, but there's no more way from CString to get a *mut c_char
in the nightly build. I found that in 0.12.0 there was a method, but now, what is the process to get that *mut c_char
?
Solution 1:[1]
let bytes = String::from_str("Test").into_bytes() + b"\0";
let cchars = bytes.map_in_place(|b| b as c_char);
let name: *mut c_char = cchars.as_mut_ptr();
The basic idea is the same as yours but there is no need to slice the Vec
explicitly; also a zero byte is appended to the buffer. See also my comment to the question.
Solution 2:[2]
Five years later and none of these solutions are working (for me, at least).
A slightly modified version of this answer:
let string: &str = "Hello, world!";
let bytes: Vec<u8> = String::from(string).into_bytes();
let mut c_chars: Vec<i8> = bytes.iter().map(| c | *c as i8).collect::<Vec<i8>>();
c_chars.push(0); // null terminator
let ptr: *mut c_char = c_chars.as_mut_ptr();
Solution 3:[3]
Look at this piece of documentation, the fn as_mut_ptr()
has been moved to the slice part of the API. So you need a mutable slice of type &mut [c_char]
. And AFAIK you cannot get that from a CString
, those would be read-only.
Instead you can use a mut Vec<c_char>
:
let mut x : Vec<c_char> = ...;
let slice = x.as_mut_slice();
let ptr = slice.as_mut_ptr();
Solution 4:[4]
Now (2022), into_raw()
works well for me, for example:
use std::ffi::CString;
use std::os::raw::c_char;
fn main() {
let c_string = CString::new("Hello!").expect("CString::new failed");
let raw: *mut c_char = c_string.into_raw();
}
Check https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_raw for more information.
Solution 5:[5]
Thanks to rodrigo's post, I found a way (very dirty, but it works) to solve my problem. Here is the code :
let mut string = std::string::String::from_str("Test");
let bytes = string.into_bytes();
let mut cchar : Vec<c_char> = bytes.map_in_place(|w| w as c_char);
let slice = cchar.as_mut_slice();
let name: *mut c_char = slice.as_mut_ptr();
A bit complex in my opinion
Solution 6:[6]
If you want to
let mut hello = b"Hello World\0".to_vec().as_mut_ptr() as *mut i8;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Vladimir Matveev |
Solution 2 | Vadim Hagedorn |
Solution 3 | Shepmaster |
Solution 4 | |
Solution 5 | |
Solution 6 |