expose function from rust
#[repr(C)]pub struct NativeVec {vec: *mut u32,vec_len: usize,vec_cap: usize,}#[no_mangle]pub extern "C" fn new_vec() -> *mut NativeVec {let v = vec![1_u32,2,3];// prevent running v's destructor so we are in complete control of the allocation// this is importantlet mut v = mem::ManuallyDrop::new(v);let nv = Box::new(NativeVec {vec: v.as_mut_ptr(),vec_len: v.len(),vec_cap: v.capacity(),});Box::into_raw(nv)}#[no_mangle]pub extern "C" fn mutate_vec(v: *mut NativeVec) {unsafe {let v = Box::from_raw(v);let v2 = Vec::from_raw_parts(v.vec, v.vec_len, v.vec_cap);println!("len {:?}", v2.len());println!("cap {:?}", v2.capacity());println!("first {:?}", v2[0]);println!("second {:?}", v2[1]);println!("third {:?}", v2[2]);drop(v2); // not nessery calling manually};}
[package]name = "c_to_rust"version = "0.1.0"authors = ["Sean <xujihui1985@gmail.com>"]edition = "2018"build = "build.rs"# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[build-dependencies]cbindgen = "0.13.1"[lib]crate-type=["cdylib", "staticlib"]
cbindgen 是用来生成c 头文件为c代码用的
build.rs
extern crate cbindgen;use std::env;use cbindgen::Language;fn main() {let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();cbindgen::Builder::new().with_crate(crate_dir).with_language(Language::C).generate().expect("Unable to generate bindings").write_to_file("target/debug/my_library.h");}
calling from c
#include "my_library.h"#include <stdio.h>int main(){NativeVec* v = new_vec();printf("length of vec is %d\n", v->vec_len);for (int i = 0; i < v->vec_len; i++){printf("vec value is is %d\n", *(v->vec + i));*(v->vec + i) = 123;}printf("addr %p\n", v->vec);mutate_vec(v);return 0;}
gcc -o main.out main.c -I./target/debug -L./target/debug -lc_to_rust
