Rust与C交互(FFI)中复杂类型的处理

来源:互联网 发布:自己设计算法 编辑:程序博客网 时间:2024/06/06 14:29

0前言

简单类型,libc都有对应的不再赘述(没有对应的bool类型),主要是 针对 struct 和 struct 数组的交互

1内容

C类型 Rust类型 说明 struct_name * *mut struct_name struct指针的转换 结构体中的数组 slice 见具体例子

struct指针 *有两层意思:
1. 指向一个struct对象
2. 指向一个struct数组

1.1指向一个struct对象

C语言如下

struct FIParam{    int n_min_face_size;    int n_roll_angle;    int b_only_detect;    unsigned long long reserved;};#define LIBDLL extern "C" _declspec(dllexport) //函数LIBDLL int      fi_create(short nChannelNum, FIParam* pParam);

Rust对应如下

extern crate libc;use libc::{c_int,c_ulonglong,c_long,c_float,c_uchar,c_short};#[repr(C)]pub struct FIParam{    pub n_min_face_size:c_int ,    pub n_roll_angle:c_int,    pub b_only_detect:c_int ,    pub reserved:c_ulonglong,}//函数 #[link(name = "库文件名(无后缀)")] extern {      pub fn fi_create(n_channel_num:c_short,p_param: *mut FIParam) ->c_int ; }

调用

let mut  param=Box::new(FIParam{    n_min_face_size:80 ,    n_roll_angle:30,    b_only_detect:1 ,    reserved:0, });let result: i32 = unsafe {    ffi::fi_create(10 as c_short, &mut *param) as i32};

1.2指向一个struct数组

C语言如下

struct FIPoint {     long x;     long y; };struct FIFacePos{    FIPoint     pt_left_eye;    FIPoint     pt_right_eye;    FIPoint     pt_mouth;    FIPoint     pt_nose;                FIFaceAngle f_angle;    int         n_quality;    unsigned char p_facial_data[512];//值得注意};#define LIBDLL extern "C" _declspec(dllexport) //函数pfps指向的是数组LIBDLL int      fi_detect_face(short nChannelID, int bpp, int nWidth, int nHeight, FIFacePos* pfps, int nMaxFaceNums, int nSampleSize = 640);

Rust对应

extern crate libc;use libc::{c_int,c_ulonglong,c_long,c_float,c_uchar,c_short};use std::mem;#[repr(C)]pub struct FIPoint{    pub x:c_long,    pub y:c_long,}impl FIPoint{    pub fn new() -> FIPoint {       FIPoint{          x: 0 as c_long,          y: 0 as c_long,      }   }}#[repr(C)]pub struct FIFacePos{   pub pt_left_eye:FIPoint,   pub pt_right_eye:FIPoint,   pub pt_mouth:FIPoint,   pub pt_nose:FIPoint,                                pub f_angle:FIFaceAngle,   pub n_quality:c_int,   pub p_facial_data:[c_uchar;512],//值得注意}impl FIFacePos{    pub fn new() -> FIFacePos {        FIFacePos{           pt_left_eye:FIPoint::new(),           pt_right_eye:FIPoint::new(),           pt_mouth:FIPoint::new(),           pt_nose:FIPoint::new(),                             f_angle:FIFaceAngle::new(),           n_quality:0 as c_int,           p_facial_data: unsafe {mem::uninitialized()},//        }     }}#[link(name = "库文件名")]extern {   pub fn fi_detect_face( n_channel_id:c_short,  bpp:c_int,  n_width:c_int,  n_height:c_int, pfps:*mut FIFacePos ,n_max_face_nums: c_int , n_sample_size:c_int )->c_int;}

调用

extern crate libc;use libc::{c_int,c_ulonglong,c_long,c_float,c_uchar,c_short};use std::mem;let max_face_num=10;let mut face_poses = Vec::new();for _ in 0..max_face_num {    face_poses.push(FIFacePos::new());}let face_num: i32 = unsafe {   fi_detect_face(0 as c_short,24 as c_int, w as c_int ,h as c_int,face_poses.as_mut_ptr(),max_face_num,640 as c_int ) as i32};

小结

只在windows 上进行测试,linux 未知