improve logging, close #6

cargo build -vv
output like this
Csbindgen can't handle this return type so ignore generate, method_name: __report_gsfailure
This commit is contained in:
neuecc 2023-03-04 21:01:50 +09:00
parent dabad3323a
commit 4710958684
8 changed files with 304 additions and 61 deletions

View File

@ -42,7 +42,7 @@ fn main() {
csbindgen::Builder::default() csbindgen::Builder::default()
.input_bindgen_file("src/lz4.rs") .input_bindgen_file("src/lz4.rs")
.method_filter(|x| { x.starts_with("LZ4")} ) .method_filter(|x| x.starts_with("LZ4"))
.rust_method_prefix("csbindgen_") .rust_method_prefix("csbindgen_")
.rust_file_header("use super::lz4;") .rust_file_header("use super::lz4;")
.rust_method_type_path("lz4") .rust_method_type_path("lz4")

View File

@ -1,3 +1,5 @@
use std::ffi::{c_char, CString};
#[allow(dead_code)] #[allow(dead_code)]
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
@ -9,6 +11,22 @@ mod lz4;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
mod lz4_ffi; mod lz4_ffi;
#[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!");
}
#[no_mangle] #[no_mangle]
pub extern "C" fn my_add(x: i32, y: i32) -> i32 { pub extern "C" fn my_add(x: i32, y: i32) -> i32 {
x + y x + y
@ -32,25 +50,57 @@ pub extern "C" fn my_bool(
true true
} }
// #[no_mangle]
// pub unsafe extern "C" fn new(x: *mut *mut Vec<u8>) {
// let v = Box::new(Vec::new());
// *x = Box::into_raw(v);
// }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn unsafe_return_string() -> *const u8 { pub extern "C" fn alloc_c_string() -> *mut c_char {
todo!(); let str = CString::new("foo bar baz").unwrap();
str.into_raw()
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn unsafe_return_string2() -> *const u8 { pub extern "C" fn free_c_string(str: *mut c_char) {
todo!(); unsafe { CString::from_raw(str) };
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn unsafe_destroy_string(s: *mut String) { pub extern "C" fn alloc_u8_string() -> *mut ByteBuffer {
unsafe { Box::from_raw(s) }; let str = format!("foo bar baz");
let buf = ByteBuffer::from_vec(str.into_bytes());
Box::into_raw(Box::new(buf))
}
#[no_mangle]
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();
} }
#[no_mangle] #[no_mangle]
@ -64,6 +114,20 @@ pub extern "C" fn delete_context(context: *mut Context) {
unsafe { Box::from_raw(context) }; unsafe { Box::from_raw(context) };
} }
#[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();
}
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Context { pub struct Context {
@ -72,24 +136,97 @@ pub struct Context {
#[test] #[test]
fn build_test() { fn build_test() {
// let path = std::env::current_dir().unwrap(); let path = std::env::current_dir().unwrap();
// println!("starting dir: {}", path.display()); // csbindgen/csbindgen-tests println!("starting dir: {}", path.display()); // csbindgen/csbindgen-tests
// // unsafe { // // unsafe {
// // let num = lz4::LZ4_versionNumber(); // // let num = lz4::LZ4_versionNumber();
// // println!("lz4 num: {}", num); // // println!("lz4 num: {}", num);
// // } // // }
// csbindgen::Builder::default()
// .input_bindgen_file("src/lz4.rs") csbindgen::Builder::default()
// .rust_method_prefix("csbindgen_") .input_extern_file("csbindgen-tests/src/lib.rs")
// .rust_file_header("use super::lz4;") .csharp_class_name("LibRust")
// .rust_method_type_path("lz4") .csharp_dll_name("csbindgen_tests")
// .csharp_class_name("LibLz4") .generate_csharp_file("dotnet-sandbox/method_call.cs")
// .csharp_dll_name("csbindgen_tests") .unwrap();
// .csharp_dll_name_if("UNITY_IOS && !UNITY_EDITOR", "__Internal") }
// .csharp_entry_point_prefix("csbindgen_")
// .csharp_method_prefix("") #[repr(C)]
// .generate_to_file("src/lz4_ffi.rs", "../dotnet-sandbox/lz4_bindgen.cs") pub struct ByteBuffer {
// .unwrap(); 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());
}
} }

View File

@ -154,7 +154,7 @@ pub fn emit_csharp(
structs_string structs_string
.push_str_ln(format!(" [StructLayout(LayoutKind.{layout_kind})]").as_str()); .push_str_ln(format!(" [StructLayout(LayoutKind.{layout_kind})]").as_str());
structs_string.push_str_ln(format!(" {accessibility} unsafe struct {name}").as_str()); structs_string.push_str_ln(format!(" {accessibility} unsafe partial struct {name}").as_str());
structs_string.push_str_ln(" {"); structs_string.push_str_ln(" {");
for field in &item.fields { for field in &item.fields {
if item.is_union { if item.is_union {

View File

@ -31,7 +31,8 @@ pub fn collect_extern_method(ast: &syn::File, options: &BindgenOptions) -> Vec<E
for item in ast.items.iter() { for item in ast.items.iter() {
if let Item::Fn(m) = item { if let Item::Fn(m) = item {
if let Some(_) = &m.sig.abi { // has extern if let Some(_) = &m.sig.abi {
// has extern
let method = parse_method(FnItem::Item(m.clone()), options); let method = parse_method(FnItem::Item(m.clone()), options);
if let Some(x) = method { if let Some(x) = method {
list.push(x); list.push(x);
@ -64,6 +65,10 @@ fn parse_method(item: FnItem, options: &BindgenOptions) -> Option<ExternMethod>
} }
let rust_type = parse_type(&t.ty); let rust_type = parse_type(&t.ty);
if rust_type.type_name.is_empty(){
println!("Csbindgen can't handle this parameter type so ignore generate, method_name: {} parameter_name: {}", method_name, parameter_name);
return None;
}
parameters.push(Parameter { parameters.push(Parameter {
name: parameter_name, name: parameter_name,
@ -76,6 +81,7 @@ fn parse_method(item: FnItem, options: &BindgenOptions) -> Option<ExternMethod>
if let ReturnType::Type(_, b) = &sig.output { if let ReturnType::Type(_, b) = &sig.output {
let rust_type = parse_type(b); let rust_type = parse_type(b);
if rust_type.type_name.is_empty() { if rust_type.type_name.is_empty() {
println!("Csbindgen can't handle this return type so ignore generate, method_name: {}", method_name);
return None; return None;
} }
@ -239,6 +245,13 @@ fn parse_type(t: &syn::Type) -> RustType {
parse_type(&t.elem).type_name // maybe ok, only retrieve type_name parse_type(&t.elem).type_name // maybe ok, only retrieve type_name
} }
syn::Type::Tuple(t) => {
if t.elems.len() == 0 {
"()".to_string()
} else {
"".to_string()
}
}
_ => "".to_string(), _ => "".to_string(),
}; };

View File

@ -56,7 +56,7 @@ pub struct RustType {
pub struct RustStruct { pub struct RustStruct {
pub struct_name: String, pub struct_name: String,
pub fields: Vec<FieldMember>, pub fields: Vec<FieldMember>,
pub is_union: bool, pub is_union: bool
} }
impl RustType { impl RustType {

View File

@ -13,26 +13,74 @@ using System.Text;
unsafe unsafe
{ {
var a = false; LibRust.call_bindgen();
var b = false;
var c = false;
Console.WriteLine(Encoding.Default);
var p = LibRust.unsafe_return_string();
var s = Encoding.UTF8.GetString(p, 5);
Console.WriteLine(s);
var z = LibRust.my_bool(true, false, true, &a, &b, &c); var cString = LibRust.alloc_c_string();
var u8String = LibRust.alloc_u8_string();
var u8Buffer = LibRust.alloc_u8_buffer();
var i32Buffer = LibRust.alloc_i32_buffer();
try
{
var str = new String((sbyte*)cString);
Console.WriteLine(str);
Console.WriteLine("----");
var str2 = Encoding.UTF8.GetString(u8String->AsSpan());
Console.WriteLine(str2);
Console.WriteLine("----");
var buffer3 = u8Buffer->AsSpan();
foreach (var item in buffer3)
{
Console.WriteLine(item);
}
Console.WriteLine("----");
var i32Span = i32Buffer->AsSpan<int>();
foreach (var item in i32Span)
{
Console.WriteLine(item);
}
}
finally
{
LibRust.free_c_string(cString);
LibRust.free_u8_string(u8String);
LibRust.free_u8_buffer(u8Buffer);
LibRust.free_i32_buffer(i32Buffer);
}
//var buf = LibRust.return_raw_buffer();
//try
//{
// var span = buf->AsSpan();
// var str = Encoding.UTF8.GetString(span);
// Console.WriteLine(str);
// //foreach (var item in span)
// //{
// // Console.WriteLine(item);
// //}
//}
//finally
//{
// LibRust.delete_raw_buffer(buf);
//}
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(z);
} }
@ -56,3 +104,19 @@ public struct Foo
{ {
[MarshalAs(UnmanagedType.U1)] public bool A; [MarshalAs(UnmanagedType.U1)] public bool A;
} }
namespace CsBindgen
{
partial struct ByteBuffer
{
public unsafe Span<byte> AsSpan()
{
return new Span<byte>(ptr, length);
}
public unsafe Span<T> AsSpan<T>()
{
return MemoryMarshal.CreateSpan(ref Unsafe.AsRef<T>(ptr), length / Unsafe.SizeOf<T>());
}
}
}

View File

@ -293,7 +293,7 @@ namespace CsBindgen
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4_stream_t_internal public unsafe partial struct LZ4_stream_t_internal
{ {
public fixed uint hashTable[4096]; public fixed uint hashTable[4096];
public byte* dictionary; public byte* dictionary;
@ -304,7 +304,7 @@ namespace CsBindgen
} }
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public unsafe struct LZ4_stream_u public unsafe partial struct LZ4_stream_u
{ {
[FieldOffset(0)] [FieldOffset(0)]
public fixed byte minStateSize[16416]; public fixed byte minStateSize[16416];
@ -313,7 +313,7 @@ namespace CsBindgen
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4_streamDecode_t_internal public unsafe partial struct LZ4_streamDecode_t_internal
{ {
public byte* externalDict; public byte* externalDict;
public byte* prefixEnd; public byte* prefixEnd;
@ -322,7 +322,7 @@ namespace CsBindgen
} }
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public unsafe struct LZ4_streamDecode_u public unsafe partial struct LZ4_streamDecode_u
{ {
[FieldOffset(0)] [FieldOffset(0)]
public fixed byte minStateSize[32]; public fixed byte minStateSize[32];
@ -331,7 +331,7 @@ namespace CsBindgen
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4HC_CCtx_internal public unsafe partial struct LZ4HC_CCtx_internal
{ {
public fixed uint hashTable[32768]; public fixed uint hashTable[32768];
public fixed ushort chainTable[65536]; public fixed ushort chainTable[65536];
@ -348,7 +348,7 @@ namespace CsBindgen
} }
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public unsafe struct LZ4_streamHC_u public unsafe partial struct LZ4_streamHC_u
{ {
[FieldOffset(0)] [FieldOffset(0)]
public fixed byte minStateSize[262200]; public fixed byte minStateSize[262200];
@ -357,7 +357,7 @@ namespace CsBindgen
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4F_frameInfo_t public unsafe partial struct LZ4F_frameInfo_t
{ {
public int blockSizeID; public int blockSizeID;
public int blockMode; public int blockMode;
@ -369,7 +369,7 @@ namespace CsBindgen
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4F_preferences_t public unsafe partial struct LZ4F_preferences_t
{ {
public LZ4F_frameInfo_t frameInfo; public LZ4F_frameInfo_t frameInfo;
public int compressionLevel; public int compressionLevel;
@ -379,26 +379,26 @@ namespace CsBindgen
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4F_cctx_s public unsafe partial struct LZ4F_cctx_s
{ {
public fixed byte _unused[1]; public fixed byte _unused[1];
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4F_compressOptions_t public unsafe partial struct LZ4F_compressOptions_t
{ {
public uint stableSrc; public uint stableSrc;
public fixed uint reserved[3]; public fixed uint reserved[3];
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4F_dctx_s public unsafe partial struct LZ4F_dctx_s
{ {
public fixed byte _unused[1]; public fixed byte _unused[1];
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe struct LZ4F_decompressOptions_t public unsafe partial struct LZ4F_decompressOptions_t
{ {
public uint stableDst; public uint stableDst;
public uint skipChecksums; public uint skipChecksums;

View File

@ -11,6 +11,9 @@ namespace CsBindgen
{ {
const string __DllName = "csbindgen_tests"; const string __DllName = "csbindgen_tests";
[DllImport(__DllName, EntryPoint = "nop", CallingConvention = CallingConvention.Cdecl)]
public static extern void nop();
[DllImport(__DllName, EntryPoint = "my_add", CallingConvention = CallingConvention.Cdecl)] [DllImport(__DllName, EntryPoint = "my_add", CallingConvention = CallingConvention.Cdecl)]
public static extern int my_add(int x, int y); public static extern int my_add(int x, int y);
@ -18,14 +21,29 @@ namespace CsBindgen
[return: MarshalAs(UnmanagedType.U1)] [return: MarshalAs(UnmanagedType.U1)]
public static extern bool my_bool([MarshalAs(UnmanagedType.U1)] bool x, [MarshalAs(UnmanagedType.U1)] bool y, [MarshalAs(UnmanagedType.U1)] bool z, bool* xr, bool* yr, bool* zr); public static extern bool my_bool([MarshalAs(UnmanagedType.U1)] bool x, [MarshalAs(UnmanagedType.U1)] bool y, [MarshalAs(UnmanagedType.U1)] bool z, bool* xr, bool* yr, bool* zr);
[DllImport(__DllName, EntryPoint = "unsafe_return_string", CallingConvention = CallingConvention.Cdecl)] [DllImport(__DllName, EntryPoint = "alloc_c_string", CallingConvention = CallingConvention.Cdecl)]
public static extern byte* unsafe_return_string(); public static extern byte* alloc_c_string();
[DllImport(__DllName, EntryPoint = "unsafe_return_string2", CallingConvention = CallingConvention.Cdecl)] [DllImport(__DllName, EntryPoint = "free_c_string", CallingConvention = CallingConvention.Cdecl)]
public static extern byte* unsafe_return_string2(); public static extern void free_c_string(byte* str);
[DllImport(__DllName, EntryPoint = "unsafe_destroy_string", CallingConvention = CallingConvention.Cdecl)] [DllImport(__DllName, EntryPoint = "alloc_u8_string", CallingConvention = CallingConvention.Cdecl)]
public static extern void unsafe_destroy_string(String* s); public static extern ByteBuffer* alloc_u8_string();
[DllImport(__DllName, EntryPoint = "free_u8_string", CallingConvention = CallingConvention.Cdecl)]
public static extern void free_u8_string(ByteBuffer* buffer);
[DllImport(__DllName, EntryPoint = "alloc_u8_buffer", CallingConvention = CallingConvention.Cdecl)]
public static extern ByteBuffer* alloc_u8_buffer();
[DllImport(__DllName, EntryPoint = "free_u8_buffer", CallingConvention = CallingConvention.Cdecl)]
public static extern void free_u8_buffer(ByteBuffer* buffer);
[DllImport(__DllName, EntryPoint = "alloc_i32_buffer", CallingConvention = CallingConvention.Cdecl)]
public static extern ByteBuffer* alloc_i32_buffer();
[DllImport(__DllName, EntryPoint = "free_i32_buffer", CallingConvention = CallingConvention.Cdecl)]
public static extern void free_i32_buffer(ByteBuffer* buffer);
[DllImport(__DllName, EntryPoint = "create_context", CallingConvention = CallingConvention.Cdecl)] [DllImport(__DllName, EntryPoint = "create_context", CallingConvention = CallingConvention.Cdecl)]
public static extern Context* create_context(); public static extern Context* create_context();
@ -33,15 +51,26 @@ namespace CsBindgen
[DllImport(__DllName, EntryPoint = "delete_context", CallingConvention = CallingConvention.Cdecl)] [DllImport(__DllName, EntryPoint = "delete_context", CallingConvention = CallingConvention.Cdecl)]
public static extern void delete_context(Context* context); public static extern void delete_context(Context* context);
[DllImport(__DllName, EntryPoint = "call_bindgen", CallingConvention = CallingConvention.Cdecl)]
public static extern void call_bindgen();
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal unsafe struct Context internal unsafe partial struct Context
{ {
[MarshalAs(UnmanagedType.U1)] public bool foo; [MarshalAs(UnmanagedType.U1)] public bool foo;
} }
[StructLayout(LayoutKind.Sequential)]
internal unsafe partial struct ByteBuffer
{
public byte* ptr;
public int length;
public int capacity;
}
} }