@@ -687,10 +687,34 @@ impl InterfaceGenerator<'_> {
687687 self . src . c_adapters ( & c_sig. sig ) ;
688688 self . src . c_adapters ( " {\n " ) ;
689689
690+ // construct optional adapters from maybe pointers to real optional
691+ // structs internally
692+ let mut optional_adapters = String :: from ( "" ) ;
693+ for ( i, ( _, param) ) in c_sig. params . iter ( ) . enumerate ( ) {
694+ let ty = & func. params [ i] . 1 ;
695+ if let Type :: Id ( id) = ty {
696+ if let TypeDefKind :: Option ( option_ty) = & self . iface . types [ * id] . kind {
697+ let ty = self . type_string ( ty) ;
698+ uwrite ! (
699+ optional_adapters,
700+ "{ty} {param};
701+ {param}.is_some = maybe_{param} != NULL;"
702+ ) ;
703+ if !self . is_empty_type ( option_ty) {
704+ uwriteln ! (
705+ optional_adapters,
706+ "if (maybe_{param}) {{
707+ {param}.val = *maybe_{param};
708+ }}" ,
709+ ) ;
710+ }
711+ }
712+ }
713+ }
714+
690715 let mut f = FunctionBindgen :: new ( self , c_sig, & import_name) ;
691716 for ( pointer, param) in f. sig . params . iter ( ) {
692- f. locals . insert ( param) . unwrap ( ) ;
693-
717+ f. locals . insert ( & param) . unwrap ( ) ;
694718 if * pointer {
695719 f. params . push ( format ! ( "*{}" , param) ) ;
696720 } else {
@@ -700,6 +724,7 @@ impl InterfaceGenerator<'_> {
700724 for ptr in f. sig . retptrs . iter ( ) {
701725 f. locals . insert ( ptr) . unwrap ( ) ;
702726 }
727+ f. src . push_str ( & optional_adapters) ;
703728 f. gen . iface . call (
704729 AbiVariant :: GuestImport ,
705730 LiftLower :: LowerArgsLiftResults ,
@@ -879,15 +904,29 @@ impl InterfaceGenerator<'_> {
879904 if i > 0 {
880905 self . src . h_fns ( ", " ) ;
881906 }
882- self . print_ty ( SourceType :: HFns , ty) ;
883- self . src . h_fns ( " " ) ;
884907 let pointer = self . is_arg_by_pointer ( ty) ;
908+ // optional param pointer flattening
909+ let optional_type = if let Type :: Id ( id) = ty {
910+ if let TypeDefKind :: Option ( option_ty) = & self . iface . types [ * id] . kind {
911+ Some ( option_ty)
912+ } else {
913+ None
914+ }
915+ } else {
916+ None
917+ } ;
918+ let ( print_ty, print_name) = if let Some ( option_ty) = optional_type {
919+ ( option_ty, format ! ( "maybe_{}" , name. to_snake_case( ) ) )
920+ } else {
921+ ( ty, name. to_snake_case ( ) )
922+ } ;
923+ self . print_ty ( SourceType :: HFns , print_ty) ;
924+ self . src . h_fns ( " " ) ;
885925 if pointer {
886926 self . src . h_fns ( "*" ) ;
887927 }
888- let name = name. to_snake_case ( ) ;
889- self . src . h_fns ( & name) ;
890- params. push ( ( pointer, name) ) ;
928+ self . src . h_fns ( & print_name) ;
929+ params. push ( ( optional_type. is_none ( ) && pointer, name. to_snake_case ( ) ) ) ;
891930 }
892931 let mut retptrs = Vec :: new ( ) ;
893932 let single_ret = ret. retptrs . len ( ) == 1 ;
@@ -2101,13 +2140,28 @@ impl Bindgen for FunctionBindgen<'_, '_> {
21012140 if i > 0 {
21022141 args. push_str ( ", " ) ;
21032142 }
2143+ let ty = & func. params [ i] . 1 ;
21042144 if * byref {
21052145 let name = self . locals . tmp ( "arg" ) ;
2106- let ty = self . gen . type_string ( & func . params [ i ] . 1 ) ;
2146+ let ty = self . gen . type_string ( ty ) ;
21072147 uwriteln ! ( self . src, "{} {} = {};" , ty, name, op) ;
21082148 args. push_str ( "&" ) ;
21092149 args. push_str ( & name) ;
21102150 } else {
2151+ if !self . gen . in_import {
2152+ if let Type :: Id ( id) = ty {
2153+ if let TypeDefKind :: Option ( option_ty) =
2154+ & self . gen . iface . types [ * id] . kind
2155+ {
2156+ if self . gen . is_empty_type ( option_ty) {
2157+ uwrite ! ( args, "{op}.is_some ? (void*)1 : NULL" ) ;
2158+ } else {
2159+ uwrite ! ( args, "{op}.is_some ? &({op}.val) : NULL" ) ;
2160+ }
2161+ continue ;
2162+ }
2163+ }
2164+ }
21112165 args. push_str ( op) ;
21122166 }
21132167 }
0 commit comments