diff --git a/src/bindgen/cdecl.rs b/src/bindgen/cdecl.rs index 1257487..4046a2b 100644 --- a/src/bindgen/cdecl.rs +++ b/src/bindgen/cdecl.rs @@ -5,7 +5,7 @@ use std::io::Write; use crate::bindgen::declarationtyperesolver::DeclarationType; -use crate::bindgen::ir::{Function, Type}; +use crate::bindgen::ir::{ArrayLength, Function, Type}; use crate::bindgen::writer::{ListType, SourceWriter}; use crate::bindgen::{Config, Language}; @@ -56,6 +56,25 @@ impl CDecl { cdecl.build_type(t, false); cdecl } + + fn from_func_arg(t: &Type, array_length: Option<&str>) -> CDecl { + let mut cdecl = CDecl::new(); + let length = match array_length { + Some(l) => l, + None => return CDecl::from_type(t), + }; + let (ty, is_const) = match t { + Type::Ptr { ty, is_const, .. } => (ty, is_const), + _ => unreachable!( + "Should never have an array length for a non pointer type {:?}", + t + ), + }; + let ptr_as_array = Type::Array(ty.clone(), ArrayLength::Value(length.to_string())); + cdecl.build_type(&ptr_as_array, *is_const); + cdecl + } + fn from_func(f: &Function, layout_vertical: bool) -> CDecl { let mut cdecl = CDecl::new(); cdecl.build_func(f, layout_vertical); @@ -66,7 +85,12 @@ impl CDecl { let args = f .args .iter() - .map(|arg| (arg.name.clone(), CDecl::from_type(&arg.ty))) + .map(|arg| { + ( + arg.name.clone(), + CDecl::from_func_arg(&arg.ty, arg.array_length.as_deref()), + ) + }) .collect(); self.declarators .push(CDeclarator::Func(args, layout_vertical)); diff --git a/src/bindgen/ir/function.rs b/src/bindgen/ir/function.rs index 79258b7..d129fd4 100644 --- a/src/bindgen/ir/function.rs +++ b/src/bindgen/ir/function.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use std::collections::HashMap; use std::io::Write; use crate::bindgen::cdecl; @@ -23,6 +24,7 @@ use crate::bindgen::writer::{Source, SourceWriter}; pub struct FunctionArgument { pub name: Option, pub ty: Type, + pub array_length: Option, } #[derive(Debug, Clone)] @@ -170,7 +172,11 @@ impl Function { .into_iter() .map(|arg| { let name = arg.name.map(|n| r.apply(&n, IdentifierType::FunctionArg)); - FunctionArgument { name, ty: arg.ty } + FunctionArgument { + name, + ty: arg.ty, + array_length: None, + } }) .collect() } @@ -183,6 +189,37 @@ impl Function { reserved::escape(name); } } + + // Save the array length of the pointer arguments which need to use + // the C-array notation + if let Some(tuples) = self.annotations.list("ptrs-as-arrays") { + let mut ptrs_as_arrays: HashMap = HashMap::new(); + for str_tuple in tuples { + let parts: Vec<&str> = str_tuple[1..str_tuple.len() - 1] + .split(';') + .map(|x| x.trim()) + .collect(); + if parts.len() != 2 { + warn!( + "{:?} does not follow the correct syntax, so the annotation is being ignored", + parts + ); + continue; + } + ptrs_as_arrays.insert(parts[0].to_string(), parts[1].to_string()); + } + + for arg in &mut self.args { + if !matches!(arg.ty, Type::Ptr { .. }) { + continue; + } + let name = match arg.name { + Some(ref name) => name, + None => continue, + }; + arg.array_length = ptrs_as_arrays.get(name).cloned(); + } + } } } @@ -337,11 +374,16 @@ impl SynFnArgHelpers for syn::FnArg { if let Type::Array(..) = ty { return Err("Array as function arguments are not supported".to_owned()); } - Ok(Some(FunctionArgument { name, ty })) + Ok(Some(FunctionArgument { + name, + ty, + array_length: None, + })) } syn::FnArg::Receiver(ref receiver) => Ok(Some(FunctionArgument { name: Some("self".to_string()), ty: gen_self_type(receiver), + array_length: None, })), } }