rust c ffi

Rust C FFI

rust-bindgen: rust 调用 c

rust-bindgen 是在编译时由头文件生成绑定代码的工具。由它封装的库称为 xxx-sys

常量宏

对于形如 #define XX (int)0 这样的有类型转换的宏是不能自动生成绑定的,可以在 wrapper.h 中写

    static const int _XX = XX;

来创建绑定。

libc: 系统库

c 类型

一般的类型在 std::os::raw 中,或者使用在 libc 中的重新绑定。

字符串

c 的字符串实际上是 &[u8] 数组,可以用 std::ffi::CStringstd::ffi::CStr, 其中 CString 拥有所有权, CStr 是借用。

指针

c 的常量指针 const int * 对应 *const i32, 一般指针 int * 对应 *mut i32. 两级指针 int ** 对应 *mut *mut int 以此类推。

结构体

rust 中定义与 c 兼容的结构体的方法为

    #[repr(C)]
    #[derive(Debug, Copy, Clone)]
    pub struct MyStruct {
        pub a: ::std::os::raw::c_int,
    }

sizeof

与 c 的 sizeof 相同的是 std::mem::sizeof

offsetof

使用 memoffsetoffset_of! 宏来获得。

如果不希望结构体内存对齐,使用 #[repr(packed)]

问题解决

传递 argc, argv

参考 stackoverflow

    extern crate libc;

    use libc::{c_char, c_int, c_void};
    use std::ffi::CString;

    extern "C" {
        fn foo(argc: *mut c_int, argv: *mut *mut *mut c_char);
    }

    fn main() {
        let mut c_args: Vec<*mut c_char> = std::env::args()
            .map(|arg| CString::new(arg).unwrap().into_raw())
            .collect();
        unsafe {
            let mut c_argc: c_int = c_args.len() as c_int;
            let mut c_argv: *mut *mut c_char = c_args.as_mut_ptr();

            foo(&mut c_argc as *mut c_int, &mut c_argv);
        }
    }

评论

Comments powered by Disqus