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 important
let 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