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();
基本思路与您相同,但没有必要显式地切片 Vec
;同时,在缓冲区末尾添加了一个零字节。另请参阅我对问题的评论。
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();
let bytes = b"Hello, world!".to_vec();
。 - Herohtar现在(2022年),into_raw()
对我来说很好用,例如:
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();
}
fn as_mut_ptr()
已经移到API的slice部分。因此,您需要一个可变的&mut [c_char]
类型的切片。据我所知,您无法从CString
中获取它们,因为那些是只读的。
相反,您可以使用mut Vec<c_char>
:
let mut x : Vec<c_char> = ...;
let slice = x.as_mut_slice();
let ptr = slice.as_mut_ptr();
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();
在我看来有点复杂
name : *mut u8
并相应地更改 API 导入代码,一切都应该正常工作。或者也许你可以使用 transmute()
,但我不知道确切的规则。 - rodrigo如果你想要
let mut hello = b"Hello World\0".to_vec().as_mut_ptr() as *mut i8;
&str
还是String
? - ShepmasterCString
应该有DerefMut
实现,并且Output = [c_char]
,这样就可以通过c_str.as_mut_ptr()
获取*mut c_char
。但我认为没有这样的实现的原因是它可能会破坏CString
的保证,即它不包含零:在这种情况下,c_str[2] = 0
是可能的。所以,我认为你的基于Vec
的解决方案很好;只要不忘记在末尾推入一个零字节,如果你的 C API 需要一个零结尾的字符串,那就没问题了。 - Vladimir Matveev