reafactoring part1

This commit is contained in:
neuecc 2023-03-05 01:03:33 +09:00
parent 4710958684
commit b986cbefff
7 changed files with 408 additions and 323 deletions

View File

@ -1,4 +1,7 @@
use std::ffi::{c_char, CString}; use std::{
collections::HashSet,
ffi::{c_char, c_void, CString},
};
#[allow(dead_code)] #[allow(dead_code)]
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -11,8 +14,6 @@ mod lz4;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
mod lz4_ffi; mod lz4_ffi;
#[no_mangle] #[no_mangle]
#[allow(improper_ctypes_definitions)] #[allow(improper_ctypes_definitions)]
pub extern "C" fn ignore_nop() -> (i32, i32) { pub extern "C" fn ignore_nop() -> (i32, i32) {
@ -20,18 +21,50 @@ pub extern "C" fn ignore_nop() -> (i32, i32) {
(1, 2) (1, 2)
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn nop() -> () { pub extern "C" fn nop() -> () {
println!("hello 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
} }
#[no_mangle]
pub extern "C" fn callback_test(cb: extern fn(a: i32) -> i32) -> i32 {
// Fn
cb(100)
}
#[no_mangle]
pub extern "C" fn create_counter_context() -> *mut c_void {
let ctx = Box::new(CounterContext {
set: HashSet::new(),
});
Box::into_raw(ctx) as *mut c_void
}
#[no_mangle]
pub unsafe extern "C" fn insert_counter_context(context: *mut c_void, value: i32) {
let mut counter = Box::from_raw(context as *mut CounterContext);
counter.set.insert(value);
Box::into_raw(counter);
}
#[no_mangle]
pub unsafe extern "C" fn delete_counter_context(context: *mut c_void) {
let counter = Box::from_raw(context as *mut CounterContext);
for value in counter.set.iter() {
println!("counter value: {}", value)
}
}
#[repr(C)]
pub struct CounterContext {
pub set: HashSet<i32>,
}
#[no_mangle] #[no_mangle]
pub extern "C" fn my_bool( pub extern "C" fn my_bool(
x: bool, x: bool,
@ -114,7 +147,6 @@ pub extern "C" fn delete_context(context: *mut Context) {
unsafe { Box::from_raw(context) }; unsafe { Box::from_raw(context) };
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn call_bindgen() { pub extern "C" fn call_bindgen() {
let path = std::env::current_dir().unwrap(); let path = std::env::current_dir().unwrap();
@ -144,7 +176,6 @@ fn build_test() {
// // println!("lz4 num: {}", num); // // println!("lz4 num: {}", num);
// // } // // }
csbindgen::Builder::default() csbindgen::Builder::default()
.input_extern_file("csbindgen-tests/src/lib.rs") .input_extern_file("csbindgen-tests/src/lib.rs")
.csharp_class_name("LibRust") .csharp_class_name("LibRust")

View File

@ -170,8 +170,8 @@ pub fn emit_csharp(
structs_string structs_string
.push_str(format!(" {}public {} {}", attr, type_name, field.name).as_str()); .push_str(format!(" {}public {} {}", attr, type_name, field.name).as_str());
if field.rust_type.is_fixed_array { if let TypeKind::FixedArray(digits, _) = &field.rust_type.type_kind {
let mut digits = field.rust_type.fixed_array_digits.clone(); let mut digits = digits.clone();
if digits == "0" { if digits == "0" {
digits = "1".to_string(); // 0 fixed array is not allowed in C# digits = "1".to_string(); // 0 fixed array is not allowed in C#
}; };

View File

@ -1,5 +1,7 @@
use crate::{builder::BindgenOptions, type_meta::*}; use crate::{builder::BindgenOptions, type_meta::*};
use std::collections::{HashMap, HashSet}; use std::{
collections::{HashMap, HashSet},
};
use syn::{ForeignItem, Item, Pat, ReturnType}; use syn::{ForeignItem, Item, Pat, ReturnType};
enum FnItem { enum FnItem {
@ -81,7 +83,10 @@ 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); println!(
"Csbindgen can't handle this return type so ignore generate, method_name: {}",
method_name
);
return None; return None;
} }
@ -114,14 +119,9 @@ pub fn collect_type_alias(ast: &syn::File) -> Vec<(String, RustType)> {
result.push(( result.push((
name, name,
RustType { RustType {
is_const: false,
is_fixed_array: false,
is_mut: false,
is_pointer: false,
is_pointer_pointer: false,
fixed_array_digits: "".to_string(),
type_name: alias.to_string(), type_name: alias.to_string(),
}, type_kind: TypeKind::Normal
}
)); ));
} }
} }
@ -209,59 +209,62 @@ pub fn reduce_struct(structs: &Vec<RustStruct>, using_types: &HashSet<String>) -
} }
fn parse_type(t: &syn::Type) -> RustType { fn parse_type(t: &syn::Type) -> RustType {
let mut has_star = false; match t {
let mut has_star_star = false;
let mut has_const = false;
let mut has_mut = false;
let mut digits: String = "".to_string();
let name = match t {
syn::Type::Ptr(t) => { syn::Type::Ptr(t) => {
has_star = true; let has_const = t.const_token.is_some();
has_const = t.const_token.is_some(); // let has_mut = t.mutability.is_some();
has_mut = t.mutability.is_some();
if let syn::Type::Path(path) = &*t.elem { if let syn::Type::Path(path) = &*t.elem {
path.path.segments.last().unwrap().ident.to_string() return RustType {
type_name: path.path.segments.last().unwrap().ident.to_string(),
type_kind: TypeKind::Pointer(if has_const { PointerType::ConstPointer } else { PointerType::MutPointer })
};
} else if let syn::Type::Ptr(t) = &*t.elem { } else if let syn::Type::Ptr(t) = &*t.elem {
has_star = false;
has_star_star = true;
if let syn::Type::Path(path) = &*t.elem { if let syn::Type::Path(path) = &*t.elem {
path.path.segments.last().unwrap().ident.to_string() return RustType {
} else { type_name: path.path.segments.last().unwrap().ident.to_string(),
"".to_string() type_kind: TypeKind::Pointer(if has_const { PointerType::ConstPointerPointer } else { PointerType::MutPointerPointer })
} };
} else { }
"".to_string() }
}
syn::Type::Path(t) => {
return RustType{
type_name:t.path.segments.last().unwrap().ident.to_string(),
type_kind: TypeKind::Normal
} }
} }
syn::Type::Path(t) => t.path.segments.last().unwrap().ident.to_string(),
syn::Type::Array(t) => { syn::Type::Array(t) => {
let mut digits = "".to_string();
if let syn::Expr::Lit(x) = &t.len { if let syn::Expr::Lit(x) = &t.len {
if let syn::Lit::Int(x) = &x.lit { if let syn::Lit::Int(x) = &x.lit {
digits = x.base10_digits().to_string(); digits = x.base10_digits().to_string();
} }
}; };
parse_type(&t.elem).type_name // maybe ok, only retrieve type_name let type_name = parse_type(&t.elem).type_name; // maybe ok, only retrieve type_name
return RustType {
type_name,
type_kind: TypeKind::FixedArray(digits, None),
};
} }
syn::Type::Tuple(t) => { syn::Type::Tuple(t) => {
if t.elems.len() == 0 { if t.elems.len() == 0 {
"()".to_string() return RustType {
} else { type_name: "()".to_string(),
"".to_string() type_kind: TypeKind::Normal,
};
};
} }
syn::Type::BareFn(_) => {
//todo!();
} }
_ => "".to_string(), _ => {}
}; };
// type_name = "" will ignore in collect method
RustType { RustType {
is_const: has_const, type_name: "".to_string(),
is_mut: has_mut, type_kind: TypeKind::Normal,
is_pointer: has_star,
is_pointer_pointer: has_star_star,
is_fixed_array: !digits.is_empty(),
type_name: name,
fixed_array_digits: digits,
} }
} }

View File

@ -41,54 +41,49 @@ pub struct ExternMethod {
pub return_type: Option<RustType>, pub return_type: Option<RustType>,
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug)]
pub struct RustType { pub struct RustType {
pub type_name: String, pub type_name: String,
pub is_pointer: bool, pub type_kind: TypeKind,
pub is_pointer_pointer: bool, }
pub is_const: bool,
pub is_mut: bool, #[derive(Clone, Debug)]
pub is_fixed_array: bool, pub enum TypeKind {
pub fixed_array_digits: String, Normal,
Pointer(PointerType),
FixedArray(String, Option<PointerType>), // digits
Function(Vec<RustType>, Option<Box<RustType>>), // parameter, return
}
#[derive(Clone, Debug)]
pub enum PointerType {
ConstPointer,
MutPointer,
ConstPointerPointer,
MutPointerPointer,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
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 {
pub fn to_string(&self, type_path: &str) -> String { pub fn to_string(&self, type_path: &str) -> String {
let mut sb = String::new(); let mut sb = String::new();
if self.is_pointer || self.is_pointer_pointer { fn emit_pointer(sb: &mut String, p: &PointerType) {
sb.push('*'); match p {
} ConstPointer => sb.push_str("*const"),
if self.is_const { MutPointer => sb.push_str("*mut"),
sb.push_str("const"); ConstPointerPointer => sb.push_str("*const *const"),
} MutPointerPointer => sb.push_str("*mut *mut"),
if self.is_mut { };
sb.push_str("mut");
}
if self.is_pointer_pointer {
if self.is_const {
sb.push_str(" *const");
} else {
sb.push_str(" *mut");
}
} }
sb.push(' '); let emit_type_name = |sb: &mut String| {
if self.is_fixed_array {
sb.push('[');
sb.push_str(self.type_name.as_str());
sb.push_str("; ");
sb.push_str(self.fixed_array_digits.as_str());
sb.push(']');
} else {
if !(self.type_name.starts_with("c_") if !(self.type_name.starts_with("c_")
|| self.type_name == "usize" || self.type_name == "usize"
|| self.type_name == "isize" || self.type_name == "isize"
@ -98,7 +93,35 @@ impl RustType {
sb.push_str("::"); sb.push_str("::");
} }
sb.push_str(self.type_name.as_str()); sb.push_str(self.type_name.as_str());
};
use PointerType::*;
use TypeKind::*;
match &self.type_kind {
Normal => {
emit_type_name(&mut sb);
} }
Pointer(p) => {
emit_pointer(&mut sb, p);
sb.push(' ');
emit_type_name(&mut sb);
}
FixedArray(digits, pointer) => {
if let Some(p) = pointer {
emit_pointer(&mut sb, p);
sb.push(' ');
}
sb.push('[');
emit_type_name(&mut sb);
sb.push_str("; ");
sb.push_str(digits.as_str());
sb.push(']');
}
Function(x, y) => {
todo!();
}
};
sb sb
} }
@ -157,7 +180,8 @@ impl RustType {
let mut sb = String::new(); let mut sb = String::new();
if self.is_fixed_array { match self.type_kind {
TypeKind::FixedArray(_, _) => {
sb.push_str("fixed "); sb.push_str("fixed ");
let type_name = convert_type_name(use_type.type_name.as_str(), options); let type_name = convert_type_name(use_type.type_name.as_str(), options);
@ -169,24 +193,35 @@ impl RustType {
}; };
sb.push_str(type_name.as_str()); sb.push_str(type_name.as_str());
} else { }
_ => {
sb.push_str(convert_type_name(use_type.type_name.as_str(), options).as_str()); sb.push_str(convert_type_name(use_type.type_name.as_str(), options).as_str());
if use_alias { if use_alias {
if use_type.is_pointer { if let TypeKind::Pointer(p) = &use_type.type_kind {
match p {
PointerType::MutPointer | PointerType::ConstPointer => {
sb.push('*'); sb.push('*');
} }
if use_type.is_pointer_pointer { PointerType::MutPointerPointer | PointerType::ConstPointerPointer => {
sb.push_str("**"); sb.push_str("**");
} }
} }
}
}
if self.is_pointer { if let TypeKind::Pointer(p) = &self.type_kind {
match p {
PointerType::MutPointer | PointerType::ConstPointer => {
sb.push('*'); sb.push('*');
} }
if self.is_pointer_pointer { PointerType::MutPointerPointer | PointerType::ConstPointerPointer => {
sb.push_str("**"); sb.push_str("**");
} }
} }
}
}
};
sb sb
} }

View File

@ -13,47 +13,54 @@ using System.Text;
unsafe unsafe
{ {
LibRust.call_bindgen(); // LibRust.call_bindgen();
var ctx = LibRust.create_counter_context();
LibRust.insert_counter_context(ctx, 10);
LibRust.insert_counter_context(ctx, 20);
LibRust.insert_counter_context(ctx, 20);
LibRust.insert_counter_context(ctx, 30);
LibRust.insert_counter_context(ctx, 99);
LibRust.delete_counter_context(ctx);
var cString = LibRust.alloc_c_string(); //var cString = LibRust.alloc_c_string();
var u8String = LibRust.alloc_u8_string(); //var u8String = LibRust.alloc_u8_string();
var u8Buffer = LibRust.alloc_u8_buffer(); //var u8Buffer = LibRust.alloc_u8_buffer();
var i32Buffer = LibRust.alloc_i32_buffer(); //var i32Buffer = LibRust.alloc_i32_buffer();
try //try
{ //{
var str = new String((sbyte*)cString); // var str = new String((sbyte*)cString);
Console.WriteLine(str); // Console.WriteLine(str);
Console.WriteLine("----"); // Console.WriteLine("----");
var str2 = Encoding.UTF8.GetString(u8String->AsSpan()); // var str2 = Encoding.UTF8.GetString(u8String->AsSpan());
Console.WriteLine(str2); // Console.WriteLine(str2);
Console.WriteLine("----"); // Console.WriteLine("----");
var buffer3 = u8Buffer->AsSpan(); // var buffer3 = u8Buffer->AsSpan();
foreach (var item in buffer3) // foreach (var item in buffer3)
{ // {
Console.WriteLine(item); // Console.WriteLine(item);
} // }
Console.WriteLine("----"); // Console.WriteLine("----");
var i32Span = i32Buffer->AsSpan<int>(); // var i32Span = i32Buffer->AsSpan<int>();
foreach (var item in i32Span) // foreach (var item in i32Span)
{ // {
Console.WriteLine(item); // Console.WriteLine(item);
} // }
} //}
finally //finally
{ //{
LibRust.free_c_string(cString); // LibRust.free_c_string(cString);
LibRust.free_u8_string(u8String); // LibRust.free_u8_string(u8String);
LibRust.free_u8_buffer(u8Buffer); // LibRust.free_u8_buffer(u8Buffer);
LibRust.free_i32_buffer(i32Buffer); // LibRust.free_i32_buffer(i32Buffer);
} //}
//var buf = LibRust.return_raw_buffer(); //var buf = LibRust.return_raw_buffer();

View File

@ -17,6 +17,15 @@ namespace CsBindgen
[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);
[DllImport(__DllName, EntryPoint = "create_counter_context", CallingConvention = CallingConvention.Cdecl)]
public static extern void* create_counter_context();
[DllImport(__DllName, EntryPoint = "insert_counter_context", CallingConvention = CallingConvention.Cdecl)]
public static extern void insert_counter_context(void* context, int value);
[DllImport(__DllName, EntryPoint = "delete_counter_context", CallingConvention = CallingConvention.Cdecl)]
public static extern void delete_counter_context(void* context);
[DllImport(__DllName, EntryPoint = "my_bool", CallingConvention = CallingConvention.Cdecl)] [DllImport(__DllName, EntryPoint = "my_bool", CallingConvention = CallingConvention.Cdecl)]
[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);