support NoNull, Box

This commit is contained in:
neuecc 2023-09-05 16:00:50 +09:00
parent 7041ca7f48
commit 510750c6b6
4 changed files with 53 additions and 21 deletions

View File

@ -1,6 +1,6 @@
use std::{ use std::{
collections::HashSet, 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)] #[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)){ pub extern "C" fn test_func_issue_39_variation1(_f: extern "C" fn(i32, i32, i32)){
} }
// #[no_mangle] #[no_mangle]
// pub extern "C" fn nonnull_parameter(_output_word_uuid: NonNull<[u8; 16]>){ pub extern "C" fn nonnull_parameter(_output_word_uuid: NonNull<[u8; 16]>){
// } }
// #[no_mangle] // #[no_mangle]
// pub extern "C" fn non_nonnull_parameter(_output_word_uuid: [u8; 16]){ // pub extern "C" fn non_nonnull_parameter(_output_word_uuid: [u8; 16]){
// } // }
// #[no_mangle] #[no_mangle]
// pub extern "C" fn non_nonnull_parameter2(_output_word_uuid: NonNull<u8>){ pub extern "C" fn non_nonnull_parameter2(_output_word_uuid: NonNull<u8>){
// } }
#[no_mangle]
pub extern "C" fn nonzero_test(_a: NonZeroI8){
}
#[no_mangle] #[no_mangle]
pub extern "C" fn ge(_f: extern "C" fn(i32, i32, i32)){ pub extern "C" fn ge(_f: extern "C" fn(i32, i32, i32)){

View File

@ -489,14 +489,24 @@ fn parse_type(t: &syn::Type) -> RustType {
fn parse_type_path(t: &syn::TypePath) -> RustType { fn parse_type_path(t: &syn::TypePath) -> RustType {
let last_segment = t.path.segments.last().unwrap(); let last_segment = t.path.segments.last().unwrap();
if let syn::PathArguments::AngleBracketed(x) = &last_segment.arguments { if let syn::PathArguments::AngleBracketed(x) = &last_segment.arguments {
// generics, only supports Option<> for null function pointer // generics
if last_segment.ident == "Option" {
if let Some(syn::GenericArgument::Type(t)) = x.args.first() { if let Some(syn::GenericArgument::Type(t)) = x.args.first() {
let rust_type = parse_type(t); let rust_type = parse_type(t);
if last_segment.ident == "Option" {
return RustType { return RustType {
type_name: "Option".to_string(), type_name: "Option".to_string(),
type_kind: TypeKind::Option(Box::new(rust_type)), 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)),
};
} }
} }
} }

View File

@ -84,6 +84,8 @@ pub enum PointerType {
MutPointerPointer, MutPointerPointer,
ConstMutPointerPointer, ConstMutPointerPointer,
MutConstPointerPointer, MutConstPointerPointer,
Box,
NonNull,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -112,7 +114,7 @@ impl RustType {
pub fn to_rust_string(&self, type_path: &str) -> String { pub fn to_rust_string(&self, type_path: &str) -> String {
let mut sb = String::new(); let mut sb = String::new();
fn emit_pointer(sb: &mut String, p: &PointerType) { fn emit_pointer(sb: &mut String, p: &PointerType) -> bool {
match p { match p {
ConstPointer => sb.push_str("*const"), ConstPointer => sb.push_str("*const"),
MutPointer => sb.push_str("*mut"), MutPointer => sb.push_str("*mut"),
@ -120,7 +122,15 @@ impl RustType {
MutPointerPointer => sb.push_str("*mut *mut"), MutPointerPointer => sb.push_str("*mut *mut"),
ConstMutPointerPointer => sb.push_str("*const *mut"), ConstMutPointerPointer => sb.push_str("*const *mut"),
MutConstPointerPointer => sb.push_str("*mut *const"), 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| { let emit_type_name = |sb: &mut String| {
@ -142,13 +152,17 @@ impl RustType {
emit_type_name(&mut sb); emit_type_name(&mut sb);
} }
Pointer(p, inner) => { Pointer(p, inner) => {
emit_pointer(&mut sb, p); let need_close = emit_pointer(&mut sb, p);
sb.push(' '); sb.push(' ');
sb.push_str(inner.to_rust_string(type_path).as_str()); sb.push_str(inner.to_rust_string(type_path).as_str());
if need_close {
sb.push('>');
}
} }
FixedArray(digits, pointer) => { FixedArray(digits, pointer) => {
let mut need_close = false;
if let Some(p) = pointer { if let Some(p) = pointer {
emit_pointer(&mut sb, p); need_close = emit_pointer(&mut sb, p);
sb.push(' '); sb.push(' ');
} }
@ -157,6 +171,9 @@ impl RustType {
sb.push_str("; "); sb.push_str("; ");
sb.push_str(digits.as_str()); sb.push_str(digits.as_str());
sb.push(']'); sb.push(']');
if need_close {
sb.push('>');
}
} }
Function(parameters, return_type) => { Function(parameters, return_type) => {
emit_type_name(&mut sb); // extern fn emit_type_name(&mut sb); // extern fn
@ -359,7 +376,7 @@ impl RustType {
); );
} }
match p { match p {
MutPointer | ConstPointer => { MutPointer | ConstPointer | NonNull | Box => {
sb.push('*'); sb.push('*');
} }
MutPointerPointer MutPointerPointer

View File

@ -53,13 +53,13 @@ namespace CsBindgen
public static extern void test_func_issue_39_variation1(delegate* unmanaged[Cdecl]<int, int, int, void> _f); public static extern void test_func_issue_39_variation1(delegate* unmanaged[Cdecl]<int, int, int, void> _f);
[DllImport(__DllName, EntryPoint = "nonnull_parameter", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [DllImport(__DllName, EntryPoint = "nonnull_parameter", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void nonnull_parameter(NonNull _output_word_uuid); public static extern void nonnull_parameter(void/* byte[] */* _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);
[DllImport(__DllName, EntryPoint = "non_nonnull_parameter2", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] [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)] [DllImport(__DllName, EntryPoint = "ge", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void ge(delegate* unmanaged[Cdecl]<int, int, int, void> _f); public static extern void ge(delegate* unmanaged[Cdecl]<int, int, int, void> _f);