From 510750c6b608c14c88ccc6f8827ec369b64de39a Mon Sep 17 00:00:00 2001 From: neuecc Date: Tue, 5 Sep 2023 16:00:50 +0900 Subject: [PATCH] support NoNull, Box --- csbindgen-tests/src/lib.rs | 19 ++++++++++++------- csbindgen/src/parser.rs | 20 +++++++++++++++----- csbindgen/src/type_meta.rs | 25 +++++++++++++++++++++---- dotnet-sandbox/NativeMethods.cs | 10 +++++----- 4 files changed, 53 insertions(+), 21 deletions(-) diff --git a/csbindgen-tests/src/lib.rs b/csbindgen-tests/src/lib.rs index fc23f84..91ec1f9 100644 --- a/csbindgen-tests/src/lib.rs +++ b/csbindgen-tests/src/lib.rs @@ -1,6 +1,6 @@ use std::{ collections::HashSet, - ffi::{c_char, c_long, c_ulong, CString}, ptr::NonNull, + ffi::{c_char, c_long, c_ulong, CString}, ptr::NonNull, num::NonZeroI8, }; #[allow(dead_code)] @@ -178,17 +178,22 @@ pub extern "C" fn test_func_issue_39(_f: extern "C" fn(i32)){ pub extern "C" fn test_func_issue_39_variation1(_f: extern "C" fn(i32, i32, i32)){ } -// #[no_mangle] -// pub extern "C" fn nonnull_parameter(_output_word_uuid: NonNull<[u8; 16]>){ -// } +#[no_mangle] +pub extern "C" fn nonnull_parameter(_output_word_uuid: NonNull<[u8; 16]>){ +} // #[no_mangle] // pub extern "C" fn non_nonnull_parameter(_output_word_uuid: [u8; 16]){ // } -// #[no_mangle] -// pub extern "C" fn non_nonnull_parameter2(_output_word_uuid: NonNull){ -// } +#[no_mangle] +pub extern "C" fn non_nonnull_parameter2(_output_word_uuid: NonNull){ +} + + +#[no_mangle] +pub extern "C" fn nonzero_test(_a: NonZeroI8){ +} #[no_mangle] pub extern "C" fn ge(_f: extern "C" fn(i32, i32, i32)){ diff --git a/csbindgen/src/parser.rs b/csbindgen/src/parser.rs index cd3726b..bdfba17 100644 --- a/csbindgen/src/parser.rs +++ b/csbindgen/src/parser.rs @@ -257,7 +257,7 @@ pub fn collect_const(ast: &syn::File, result: &mut Vec) { format!("{}", i.base10_parse::().unwrap()) } syn::Lit::Float(f) => { - format!("{}", f.base10_parse::().unwrap()) + format!("{}", f.base10_parse::().unwrap()) } syn::Lit::Bool(b) => { format!("{}", b.value) @@ -489,14 +489,24 @@ fn parse_type(t: &syn::Type) -> RustType { fn parse_type_path(t: &syn::TypePath) -> RustType { let last_segment = t.path.segments.last().unwrap(); if let syn::PathArguments::AngleBracketed(x) = &last_segment.arguments { - // generics, only supports Option<> for null function pointer - if last_segment.ident == "Option" { - if let Some(syn::GenericArgument::Type(t)) = x.args.first() { - let rust_type = parse_type(t); + // generics + if let Some(syn::GenericArgument::Type(t)) = x.args.first() { + let rust_type = parse_type(t); + if last_segment.ident == "Option" { return RustType { type_name: "Option".to_string(), type_kind: TypeKind::Option(Box::new(rust_type)), }; + } else if last_segment.ident == "NonNull" { + return RustType { + type_name: "NonNull".to_string(), + type_kind: TypeKind::Pointer(PointerType::NonNull, Box::new(rust_type)), + }; + } else if last_segment.ident == "Box" { + return RustType { + type_name: "Box".to_string(), + type_kind: TypeKind::Pointer(PointerType::Box, Box::new(rust_type)), + }; } } } diff --git a/csbindgen/src/type_meta.rs b/csbindgen/src/type_meta.rs index 5466f00..7a856ba 100644 --- a/csbindgen/src/type_meta.rs +++ b/csbindgen/src/type_meta.rs @@ -84,6 +84,8 @@ pub enum PointerType { MutPointerPointer, ConstMutPointerPointer, MutConstPointerPointer, + Box, + NonNull, } #[derive(Clone, Debug)] @@ -112,7 +114,7 @@ impl RustType { pub fn to_rust_string(&self, type_path: &str) -> String { let mut sb = String::new(); - fn emit_pointer(sb: &mut String, p: &PointerType) { + fn emit_pointer(sb: &mut String, p: &PointerType) -> bool { match p { ConstPointer => sb.push_str("*const"), MutPointer => sb.push_str("*mut"), @@ -120,7 +122,15 @@ impl RustType { MutPointerPointer => sb.push_str("*mut *mut"), ConstMutPointerPointer => sb.push_str("*const *mut"), MutConstPointerPointer => sb.push_str("*mut *const"), + NonNull => sb.push_str("NonNull<"), + Box => sb.push_str("Box<"), }; + + // return NonNull or Box requires close angle + match p { + NonNull | Box => true, + _ => false, + } } let emit_type_name = |sb: &mut String| { @@ -142,13 +152,17 @@ impl RustType { emit_type_name(&mut sb); } Pointer(p, inner) => { - emit_pointer(&mut sb, p); + let need_close = emit_pointer(&mut sb, p); sb.push(' '); sb.push_str(inner.to_rust_string(type_path).as_str()); + if need_close { + sb.push('>'); + } } FixedArray(digits, pointer) => { + let mut need_close = false; if let Some(p) = pointer { - emit_pointer(&mut sb, p); + need_close = emit_pointer(&mut sb, p); sb.push(' '); } @@ -157,6 +171,9 @@ impl RustType { sb.push_str("; "); sb.push_str(digits.as_str()); sb.push(']'); + if need_close { + sb.push('>'); + } } Function(parameters, return_type) => { emit_type_name(&mut sb); // extern fn @@ -359,7 +376,7 @@ impl RustType { ); } match p { - MutPointer | ConstPointer => { + MutPointer | ConstPointer | NonNull | Box => { sb.push('*'); } MutPointerPointer diff --git a/dotnet-sandbox/NativeMethods.cs b/dotnet-sandbox/NativeMethods.cs index 6b00708..88f4cad 100644 --- a/dotnet-sandbox/NativeMethods.cs +++ b/dotnet-sandbox/NativeMethods.cs @@ -53,13 +53,13 @@ namespace CsBindgen public static extern void test_func_issue_39_variation1(delegate* unmanaged[Cdecl] _f); [DllImport(__DllName, EntryPoint = "nonnull_parameter", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern void nonnull_parameter(NonNull _output_word_uuid); - - [DllImport(__DllName, EntryPoint = "non_nonnull_parameter", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern void non_nonnull_parameter(void/* byte[] */ _output_word_uuid); + public static extern void nonnull_parameter(void/* byte[] */* _output_word_uuid); [DllImport(__DllName, EntryPoint = "non_nonnull_parameter2", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern void non_nonnull_parameter2(byte _output_word_uuid); + public static extern void non_nonnull_parameter2(byte* _output_word_uuid); + + [DllImport(__DllName, EntryPoint = "nonzero_test", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void nonzero_test(NonZeroI8 _a, U32Transparent _b); [DllImport(__DllName, EntryPoint = "ge", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] public static extern void ge(delegate* unmanaged[Cdecl] _f);