2023-03-04 12:01:50 +00:00
|
|
|
use std::ffi::{c_char, CString};
|
|
|
|
|
2023-02-28 05:49:04 +00:00
|
|
|
#[allow(dead_code)]
|
|
|
|
#[allow(non_snake_case)]
|
|
|
|
#[allow(non_camel_case_types)]
|
|
|
|
#[allow(non_upper_case_globals)]
|
|
|
|
mod lz4;
|
2023-02-26 18:31:44 +00:00
|
|
|
|
2023-02-27 23:08:46 +00:00
|
|
|
#[allow(dead_code)]
|
|
|
|
#[allow(non_snake_case)]
|
|
|
|
#[allow(non_camel_case_types)]
|
|
|
|
mod lz4_ffi;
|
2023-02-26 18:31:44 +00:00
|
|
|
|
2023-03-04 12:01:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
#[allow(improper_ctypes_definitions)]
|
|
|
|
pub extern "C" fn ignore_nop() -> (i32, i32) {
|
|
|
|
println!("hello ignore!");
|
|
|
|
(1, 2)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn nop() -> () {
|
|
|
|
println!("hello nop!");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-02-28 05:49:04 +00:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn my_add(x: i32, y: i32) -> i32 {
|
|
|
|
x + y
|
|
|
|
}
|
|
|
|
|
2023-03-03 08:49:05 +00:00
|
|
|
#[no_mangle]
|
2023-03-04 05:39:45 +00:00
|
|
|
pub extern "C" fn my_bool(
|
|
|
|
x: bool,
|
|
|
|
y: bool,
|
|
|
|
z: bool,
|
|
|
|
xr: *mut bool,
|
|
|
|
yr: *mut bool,
|
|
|
|
zr: *mut bool,
|
|
|
|
) -> bool {
|
2023-03-03 08:49:05 +00:00
|
|
|
unsafe {
|
|
|
|
*xr = x;
|
|
|
|
*yr = y;
|
|
|
|
*zr = z;
|
|
|
|
}
|
2023-03-04 05:39:45 +00:00
|
|
|
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
2023-03-04 12:01:50 +00:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn alloc_c_string() -> *mut c_char {
|
|
|
|
let str = CString::new("foo bar baz").unwrap();
|
|
|
|
str.into_raw()
|
|
|
|
}
|
2023-03-04 05:39:45 +00:00
|
|
|
|
|
|
|
#[no_mangle]
|
2023-03-04 12:01:50 +00:00
|
|
|
pub extern "C" fn free_c_string(str: *mut c_char) {
|
|
|
|
unsafe { CString::from_raw(str) };
|
2023-03-04 05:39:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2023-03-04 12:01:50 +00:00
|
|
|
pub extern "C" fn alloc_u8_string() -> *mut ByteBuffer {
|
|
|
|
let str = format!("foo bar baz");
|
|
|
|
let buf = ByteBuffer::from_vec(str.into_bytes());
|
|
|
|
Box::into_raw(Box::new(buf))
|
2023-03-04 05:39:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2023-03-04 12:01:50 +00:00
|
|
|
pub unsafe extern "C" fn free_u8_string(buffer: *mut ByteBuffer) {
|
|
|
|
let buf = Box::from_raw(buffer);
|
|
|
|
// drop inner buffer, if you need String, use String::from_utf8_unchecked(buf.destroy_into_vec()) instead.
|
|
|
|
buf.destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn alloc_u8_buffer() -> *mut ByteBuffer {
|
|
|
|
let vec: Vec<u8> = vec![1, 10, 100];
|
|
|
|
let buf = ByteBuffer::from_vec(vec);
|
|
|
|
Box::into_raw(Box::new(buf))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn free_u8_buffer(buffer: *mut ByteBuffer) {
|
|
|
|
let buf = Box::from_raw(buffer);
|
|
|
|
// drop inner buffer, if you need Vec<u8>, use buf.destroy_into_vec() instead.
|
|
|
|
buf.destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn alloc_i32_buffer() -> *mut ByteBuffer {
|
|
|
|
let vec: Vec<i32> = vec![1, 10, 100, 1000, 10000];
|
|
|
|
let buf = ByteBuffer::from_vec_struct(vec);
|
|
|
|
Box::into_raw(Box::new(buf))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn free_i32_buffer(buffer: *mut ByteBuffer) {
|
|
|
|
let buf = Box::from_raw(buffer);
|
|
|
|
// drop inner buffer, if you need Vec<i32>, use buf.destroy_into_vec_struct::<i32>() instead.
|
|
|
|
buf.destroy();
|
2023-03-03 08:49:05 +00:00
|
|
|
}
|
|
|
|
|
2023-03-04 05:54:48 +00:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn create_context() -> *mut Context {
|
|
|
|
let ctx = Box::new(Context { foo: true });
|
|
|
|
Box::into_raw(ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn delete_context(context: *mut Context) {
|
|
|
|
unsafe { Box::from_raw(context) };
|
|
|
|
}
|
|
|
|
|
2023-03-04 12:01:50 +00:00
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn call_bindgen() {
|
|
|
|
let path = std::env::current_dir().unwrap();
|
|
|
|
println!("starting dir: {}", path.display()); // csbindgen/csbindgen-tests
|
|
|
|
|
|
|
|
csbindgen::Builder::default()
|
|
|
|
.input_extern_file("../../../../csbindgen-tests/src/lib.rs")
|
|
|
|
.csharp_class_name("LibRust")
|
|
|
|
.csharp_dll_name("csbindgen_tests")
|
|
|
|
.generate_csharp_file("../../../../dotnet-sandbox/method_call.cs")
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
|
2023-03-04 05:54:48 +00:00
|
|
|
#[repr(C)]
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
|
|
pub struct Context {
|
|
|
|
pub foo: bool,
|
|
|
|
}
|
|
|
|
|
2023-02-27 22:18:10 +00:00
|
|
|
#[test]
|
|
|
|
fn build_test() {
|
2023-03-04 12:01:50 +00:00
|
|
|
let path = std::env::current_dir().unwrap();
|
|
|
|
println!("starting dir: {}", path.display()); // csbindgen/csbindgen-tests
|
2023-02-26 18:31:44 +00:00
|
|
|
|
2023-02-28 05:49:04 +00:00
|
|
|
// // unsafe {
|
|
|
|
// // let num = lz4::LZ4_versionNumber();
|
|
|
|
// // println!("lz4 num: {}", num);
|
|
|
|
// // }
|
2023-02-26 18:31:44 +00:00
|
|
|
|
2023-03-04 12:01:50 +00:00
|
|
|
|
|
|
|
csbindgen::Builder::default()
|
|
|
|
.input_extern_file("csbindgen-tests/src/lib.rs")
|
|
|
|
.csharp_class_name("LibRust")
|
|
|
|
.csharp_dll_name("csbindgen_tests")
|
|
|
|
.generate_csharp_file("dotnet-sandbox/method_call.cs")
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct ByteBuffer {
|
|
|
|
ptr: *mut u8,
|
|
|
|
length: i32,
|
|
|
|
capacity: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ByteBuffer {
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
self.length
|
|
|
|
.try_into()
|
|
|
|
.expect("buffer length negative or overflowed")
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn from_vec(bytes: Vec<u8>) -> Self {
|
|
|
|
let length = i32::try_from(bytes.len()).expect("buffer length cannot fit into a i32.");
|
|
|
|
let capacity =
|
|
|
|
i32::try_from(bytes.capacity()).expect("buffer capacity cannot fit into a i32.");
|
|
|
|
|
|
|
|
// keep memory until call delete
|
|
|
|
let mut v = std::mem::ManuallyDrop::new(bytes);
|
|
|
|
|
|
|
|
Self {
|
|
|
|
ptr: v.as_mut_ptr(),
|
|
|
|
length,
|
|
|
|
capacity,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn from_vec_struct<T: Sized>(bytes: Vec<T>) -> Self {
|
|
|
|
let element_size = std::mem::size_of::<T>() as i32;
|
|
|
|
|
|
|
|
let length = (bytes.len() as i32) * element_size;
|
|
|
|
let capacity = (bytes.capacity() as i32) * element_size;
|
|
|
|
|
|
|
|
let mut v = std::mem::ManuallyDrop::new(bytes);
|
|
|
|
|
|
|
|
Self {
|
|
|
|
ptr: v.as_mut_ptr() as *mut u8,
|
|
|
|
length,
|
|
|
|
capacity,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn destroy_into_vec(self) -> Vec<u8> {
|
|
|
|
if self.ptr.is_null() {
|
|
|
|
vec![]
|
|
|
|
} else {
|
|
|
|
let capacity: usize = self
|
|
|
|
.capacity
|
|
|
|
.try_into()
|
|
|
|
.expect("buffer capacity negative or overflowed");
|
|
|
|
let length: usize = self
|
|
|
|
.length
|
|
|
|
.try_into()
|
|
|
|
.expect("buffer length negative or overflowed");
|
|
|
|
|
|
|
|
unsafe { Vec::from_raw_parts(self.ptr, length, capacity) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn destroy_into_vec_struct<T: Sized>(self) -> Vec<T> {
|
|
|
|
if self.ptr.is_null() {
|
|
|
|
vec![]
|
|
|
|
} else {
|
|
|
|
let element_size = std::mem::size_of::<T>() as i32;
|
|
|
|
let length = (self.length * element_size) as usize;
|
|
|
|
let capacity = (self.capacity * element_size) as usize;
|
|
|
|
|
|
|
|
unsafe { Vec::from_raw_parts(self.ptr as *mut T, length, capacity) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn destroy(self) {
|
|
|
|
drop(self.destroy_into_vec());
|
|
|
|
}
|
2023-02-26 18:31:44 +00:00
|
|
|
}
|