Rust : rust-bindgen中ffi中类型转换

在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]

五、边界值的问题
这个需要仔细考虑一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值