在rust-bindgen中,经常会碰到各种转换。下面是ctp bindings.rs中一个实例,这些类型需要进行转换,才方便使用。
一、常见的bindings.rs中示例
pub type TThostFtdcDateTimeType = [::std::os::raw::c_char; 17usize];
pub type TThostFtdcWeakPasswordSourceType = ::std::os::raw::c_char;
pub type TThostFtdcRandomStringType = [::std::os::raw::c_char; 17usize];
pub type TThostFtdcOptSelfCloseFlagType = ::std::os::raw::c_char;
pub type TThostFtdcBizTypeType = ::std::os::raw::c_char;
pub type TThostFtdcAppTypeType = ::std::os::raw::c_char;
pub type TThostFtdcAppIDType = [::std::os::raw::c_char; 33usize];
pub type TThostFtdcSystemInfoLenType = ::std::os::raw::c_int;
pub type TThostFtdcAdditionalInfoLenType = ::std::os::raw::c_int;
pub type TThostFtdcClientSystemInfoType = [::std::os::raw::c_char; 273usize];
pub type TThostFtdcAdditionalInfoType = [::std::os::raw::c_char; 261usize];
pub type TThostFtdcBase64ClientSystemInfoType = [::std::os::raw::c_char; 365usize];
pub type TThostFtdcBase64AdditionalInfoType = [::std::os::raw::c_char; 349usize];
pub type TThostFtdcCurrentAuthMethodType = ::std::os::raw::c_int;
二、转换的常见方法
以下主要参考了
https://github.com/dovahcrow/xtp-rs
trait FromCBuf<'a> {
fn from_c_buf(b: &'a [c_char]) -> Self;
}
impl<'a> FromCBuf<'a> for &'a CStr {
fn from_c_buf(b: &'a [c_char]) -> Self {
// convert from &[i8] to &[u8]
let b = unsafe { &*(b as *const _ as *const [u8]) };
match b.iter().position(|&c| c == 0u8) {
Some(pos) => unsafe { CStr::from_bytes_with_nul_unchecked(&b[..=pos]) },
None => {
let s = String::from_utf8(b.to_vec());
println!("{:?}", s);
unreachable!("String without null end"); // to be sure follows this !
}
}
}
}
impl<'a> FromCBuf<'a> for String {
fn from_c_buf(b: &'a [c_char]) -> Self {
// convert from &[i8] to &[u8]
let b = unsafe { &*(b as *const _ as *const [u8]) };
let slice = match b.iter().position(|&c| c == 0u8) {
Some(pos) => &b[..pos],
None => b,
};
unsafe { String::from_utf8_unchecked(slice.to_vec()) }
}
}
trait ToCBuf {
fn to_c_buf16(&self) -> [c_char; 16usize];
fn to_c_buf64(&self) -> [c_char; 64usize];
}
impl ToCBuf for &CStr {
fn to_c_buf16(&self) -> [c_char; 16usize] {
let mut sarr = [0i8; 16];
let len = self.to_bytes().len().min(16);
for (i, &byte) in self.to_bytes()[..len].iter().enumerate() {
sarr[i] = byte as i8;
}
sarr
}
fn to_c_buf64(&self) -> [c_char; 64usize] {
let mut sarr = [0i8; 64];
let len = self.to_bytes().len().min(64);
for (i, &byte) in self.to_bytes()[..len].iter().enumerate() {
sarr[i] = byte as i8;
}
sarr
}
}
impl ToCBuf for String {
fn to_c_buf16(&self) -> [c_char; 16usize] {
let mut sarr = [0i8; 16];
let len = self.as_bytes().len().min(16);
for (i, &byte) in self.as_bytes()[..len].iter().enumerate() {
sarr[i] = byte as i8;
}
sarr
}
fn to_c_buf64(&self) -> [c_char; 64usize] {
let mut sarr = [0i8; 64];
let len = self.as_bytes().len().min(64);
for (i, &byte) in self.as_bytes()[..len].iter().enumerate() {
sarr[i] = byte as i8;
}
sarr
}
}
三、具体的一些类型
比如:
::std::os::raw::c_char; =>i8
::std::os::raw::c_int =>i32;
[::std::os::raw::c_char;15usize] =>String
需要写一个脚本,把binding.rs中的内容再理一下,binding.rs中是机器翻译的,并不好用,需要转换一下,便于写代码。
这个难度不大。
四、其它类型
*mut *mut ::std::os::raw::c_char => &[&str]
五、边界值的问题
这个需要仔细考虑一下。