diff --git a/csbindgen-tests/build.rs b/csbindgen-tests/build.rs index c67654b..c72ef29 100644 --- a/csbindgen-tests/build.rs +++ b/csbindgen-tests/build.rs @@ -84,6 +84,8 @@ fn main() -> Result<(), Box> { csbindgen::Builder::default() .input_extern_file("src/lib.rs") + .input_extern_file("src/others.rs") + //.input_extern_files(&["src/lib.rs"]) .csharp_class_name("NativeMethods") .csharp_dll_name("csbindgen_tests") .csharp_use_function_pointer(true) diff --git a/csbindgen-tests/src/lib.rs b/csbindgen-tests/src/lib.rs index 8a7e32d..479e68b 100644 --- a/csbindgen-tests/src/lib.rs +++ b/csbindgen-tests/src/lib.rs @@ -3,6 +3,8 @@ use std::{ ffi::{c_char, c_long, c_ulong, c_void, CString}, }; + + #[allow(dead_code)] #[allow(non_snake_case)] #[allow(non_camel_case_types)] @@ -58,6 +60,14 @@ mod lz4_ffi; // #[allow(non_camel_case_types)] // mod zstd_ffi; +mod others; +pub use others::HogeMoge; + +#[no_mangle] +pub extern "C" fn other_1(hoge: HogeMoge){ + println!("{}", hoge); +} + #[no_mangle] pub extern "C" fn nest_test( _f: ::std::option::Option< @@ -74,6 +84,7 @@ pub extern "C" fn nest_test( + #[allow(non_camel_case_types)] pub type LONG_PTR = ::std::os::raw::c_longlong; #[allow(non_camel_case_types)] diff --git a/csbindgen-tests/src/others.rs b/csbindgen-tests/src/others.rs new file mode 100644 index 0000000..82d6950 --- /dev/null +++ b/csbindgen-tests/src/others.rs @@ -0,0 +1,9 @@ + + + +#[repr(i32)] +#[derive(Debug, Copy, Clone)] +pub enum HogeMoge{ + X = 0, + Y = 1, +} \ No newline at end of file diff --git a/csbindgen/src/builder.rs b/csbindgen/src/builder.rs index c5dcf5d..7110b15 100644 --- a/csbindgen/src/builder.rs +++ b/csbindgen/src/builder.rs @@ -13,7 +13,7 @@ pub struct Builder { pub struct BindgenOptions { pub input_bindgen_file: String, - pub input_extern_file: String, + pub input_extern_files: Vec, pub method_filter: fn(method_name: String) -> bool, pub rust_method_type_path: String, pub rust_method_prefix: String, @@ -34,7 +34,7 @@ impl Default for Builder { Self { options: BindgenOptions { input_bindgen_file: "".to_string(), - input_extern_file: "".to_string(), + input_extern_files: vec![], method_filter: |x| !x.starts_with('_'), rust_method_type_path: "".to_string(), rust_method_prefix: "csbindgen_".to_string(), @@ -47,7 +47,7 @@ impl Default for Builder { csharp_class_accessibility: "internal".to_string(), csharp_if_symbol: "".to_string(), csharp_if_dll_name: "".to_string(), - csharp_use_function_pointer: true + csharp_use_function_pointer: true, }, } } @@ -64,9 +64,11 @@ impl Builder { self } - /// Change an input .rs file for collect extern methods to C# binding. + /// Add an input .rs file for collect extern methods to C# binding. pub fn input_extern_file>(mut self, input_extern_file: T) -> Builder { - self.options.input_extern_file = input_extern_file.into(); + self.options + .input_extern_files + .push(input_extern_file.into()); self } @@ -137,7 +139,10 @@ impl Builder { /// configure C# class accessibility, default is internal /// `{csharp_class_accessibility} static unsafe partial class NativeMethods` - pub fn csharp_class_accessibility>(mut self, csharp_class_accessibility: T) -> Builder { + pub fn csharp_class_accessibility>( + mut self, + csharp_class_accessibility: T, + ) -> Builder { self.options.csharp_class_accessibility = csharp_class_accessibility.into(); self } @@ -168,7 +173,7 @@ impl Builder { csharp_file.flush()?; } - if !self.options.input_extern_file.is_empty() { + if !self.options.input_extern_files.is_empty() { let (_, csharp) = generate(GenerateKind::InputExtern, &self.options)?; let mut csharp_file = make_file(csharp_output_path.as_ref())?; @@ -199,7 +204,7 @@ impl Builder { csharp_file.flush()?; } - if !self.options.input_extern_file.is_empty() { + if !self.options.input_extern_files.is_empty() { let (rust, csharp) = generate(GenerateKind::InputExtern, &self.options)?; if let Some(rust) = rust { diff --git a/csbindgen/src/lib.rs b/csbindgen/src/lib.rs index 60c5adc..f888dc0 100644 --- a/csbindgen/src/lib.rs +++ b/csbindgen/src/lib.rs @@ -14,7 +14,7 @@ use emitter::*; use field_map::FieldMap; use parser::*; use std::{collections::HashSet, error::Error}; -use type_meta::RustType; +use type_meta::{ExternMethod, RustEnum, RustStruct, RustType}; enum GenerateKind { InputBindgen, @@ -25,21 +25,30 @@ pub(crate) fn generate( generate_kind: GenerateKind, options: &BindgenOptions, ) -> Result<(Option, String), Box> { - let path = match generate_kind { - GenerateKind::InputBindgen => &options.input_bindgen_file, - GenerateKind::InputExtern => &options.input_extern_file, + let temp_input = [options.input_bindgen_file.clone()]; + let (paths, generate_rust) = match generate_kind { + GenerateKind::InputBindgen => (temp_input.as_slice(), true), + GenerateKind::InputExtern => (options.input_extern_files.as_slice(), false), }; - let file_content = std::fs::read_to_string(path) - .expect(("input file not found, path:".to_string() + path).as_str()); - let file_ast = syn::parse_file(file_content.as_str())?; - let (methods, generate_rust) = match generate_kind { - GenerateKind::InputBindgen => (collect_foreign_method(&file_ast, options), true), - GenerateKind::InputExtern => (collect_extern_method(&file_ast, options), false), - }; - let aliases = collect_type_alias(&file_ast); - let structs = collect_struct(&file_ast); - let enums = collect_enum(&file_ast); + let mut methods: Vec = vec![]; + let mut aliases = AliasMap::new(); + let mut structs: Vec = vec![]; + let mut enums: Vec = vec![]; + + for path in paths { + let file_content = std::fs::read_to_string(path) + .expect(("input file not found, path:".to_string() + path).as_str()); + let file_ast = syn::parse_file(file_content.as_str())?; + + match generate_kind { + GenerateKind::InputBindgen => collect_foreign_method(&file_ast, options, &mut methods), + GenerateKind::InputExtern => collect_extern_method(&file_ast, options, &mut methods), + }; + collect_type_alias(&file_ast, &mut aliases); + collect_struct(&file_ast, &mut structs); + collect_enum(&file_ast, &mut enums); + } // collect using_types let mut using_types = HashSet::new(); diff --git a/csbindgen/src/parser.rs b/csbindgen/src/parser.rs index 4ddee93..bdc8755 100644 --- a/csbindgen/src/parser.rs +++ b/csbindgen/src/parser.rs @@ -7,9 +7,11 @@ enum FnItem { Item(syn::ItemFn), } -pub fn collect_foreign_method(ast: &syn::File, options: &BindgenOptions) -> Vec { - let mut list: Vec = Vec::new(); - +pub fn collect_foreign_method( + ast: &syn::File, + options: &BindgenOptions, + list: &mut Vec, +) { for item in ast.items.iter() { if let Item::ForeignMod(m) = item { for item in m.items.iter() { @@ -22,13 +24,13 @@ pub fn collect_foreign_method(ast: &syn::File, options: &BindgenOptions) -> Vec< } } } - - list } -pub fn collect_extern_method(ast: &syn::File, options: &BindgenOptions) -> Vec { - let mut list: Vec = Vec::new(); - +pub fn collect_extern_method( + ast: &syn::File, + options: &BindgenOptions, + list: &mut Vec, +) { for item in ast.items.iter() { if let Item::Fn(m) = item { if m.sig.abi.is_some() { @@ -40,8 +42,6 @@ pub fn collect_extern_method(ast: &syn::File, options: &BindgenOptions) -> Vec Option { @@ -112,8 +112,7 @@ fn parse_method(item: FnItem, options: &BindgenOptions) -> Option None } -pub fn collect_type_alias(ast: &syn::File) -> AliasMap { - let mut result = AliasMap::new(); +pub fn collect_type_alias(ast: &syn::File, result: &mut AliasMap) { for item in ast.items.iter() { if let Item::Type(t) = item { let name = t.ident.to_string(); @@ -135,14 +134,10 @@ pub fn collect_type_alias(ast: &syn::File) -> AliasMap { } } } - - result } -pub fn collect_struct(ast: &syn::File) -> Vec { +pub fn collect_struct(ast: &syn::File, result: &mut Vec) { // collect union or struct - let mut result = Vec::new(); - for item in ast.items.iter() { if let Item::Union(t) = item { let struct_name = t.ident.to_string(); @@ -165,8 +160,6 @@ pub fn collect_struct(ast: &syn::File) -> Vec { }; } } - - result } fn collect_fields(fields: &syn::FieldsNamed) -> Vec { @@ -185,9 +178,7 @@ fn collect_fields(fields: &syn::FieldsNamed) -> Vec { result } -pub fn collect_enum(ast: &syn::File) -> Vec { - let mut result = Vec::new(); - +pub fn collect_enum(ast: &syn::File, result: &mut Vec) { for item in ast.items.iter() { if let Item::Enum(t) = item { let mut repr = None; @@ -221,8 +212,6 @@ pub fn collect_enum(ast: &syn::File) -> Vec { }); } } - - result } pub fn reduce_struct( diff --git a/dotnet-sandbox/NativeMethods.cs b/dotnet-sandbox/NativeMethods.cs index 6cc8ab6..ac66d26 100644 --- a/dotnet-sandbox/NativeMethods.cs +++ b/dotnet-sandbox/NativeMethods.cs @@ -12,6 +12,9 @@ namespace CsBindgen { const string __DllName = "csbindgen_tests"; + [DllImport(__DllName, EntryPoint = "other_1", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void other_1(HogeMoge hoge); + [DllImport(__DllName, EntryPoint = "nest_test", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] public static extern void nest_test(delegate* unmanaged[Cdecl]*, int> _f); @@ -173,6 +176,12 @@ namespace CsBindgen C = 10, } + internal enum HogeMoge : int + { + X = 0, + Y = 1, + } + } \ No newline at end of file