@@ -175,9 +175,9 @@ def method_stub_name(cls, sel):
175175 return f"AOT_{ cls } _{ sanitize_selector (sel )} "
176176
177177
178- def build_objc_call (cls , sel , args , target = "target" , is_static = False , class_var = None , ret = None ):
178+ def build_objc_call (cls , sel , args , target = "target" , is_static = False , class_var = None , ret = None , object_types = frozenset () ):
179179 if class_var :
180- return _build_msgsend_call (class_var if is_static else target , sel , ret or "id" , args )
180+ return _build_msgsend_call (class_var if is_static else target , sel , ret or "id" , args , object_types )
181181 if is_static :
182182 receiver = cls
183183 else :
@@ -189,23 +189,27 @@ def build_objc_call(cls, sel, args, target="target", is_static=False, class_var=
189189 return f"[{ receiver } { expr } ]"
190190
191191
192- def _c_type (t ):
193- return t if t not in TYPES else TYPES [t ]["c_type" ]
192+ def _c_type (t , object_types = frozenset ()):
193+ if t in TYPES :
194+ return TYPES [t ]["c_type" ]
195+ if t in object_types :
196+ return "id"
197+ return t
194198
195199
196- def _build_msgsend_call (receiver , sel , ret , args ):
197- c_ret = _c_type (ret )
198- c_args = ["id" , "SEL" ] + [_c_type (a ) for a in args ]
200+ def _build_msgsend_call (receiver , sel , ret , args , object_types = frozenset () ):
201+ c_ret = _c_type (ret , object_types )
202+ c_args = ["id" , "SEL" ] + [_c_type (a , object_types ) for a in args ]
199203 cast = f"(({ c_ret } (*)({ ', ' .join (c_args )} ))objc_msgSend)"
200204 arg_str = ", " .join (f"arg{ i } " for i in range (len (args )))
201205 suffix = f", { arg_str } " if arg_str else ""
202206 return f"{ cast } ((id){ receiver } , @selector({ sel } ){ suffix } )"
203207
204208
205- def build_super_call (cls , sel , ret , args , struct_tag = False ):
209+ def build_super_call (cls , sel , ret , args , struct_tag = False , object_types = frozenset () ):
206210 prefix = "struct " if struct_tag else ""
207- c_ret = _c_type (ret )
208- c_args = [f"{ prefix } objc_super*" , "SEL" ] + [_c_type (a ) for a in args ]
211+ c_ret = _c_type (ret , object_types )
212+ c_args = [f"{ prefix } objc_super*" , "SEL" ] + [_c_type (a , object_types ) for a in args ]
209213 cast = f"(({ c_ret } (*)({ ', ' .join (c_args )} ))"
210214 arg_str = ", " .join (f"arg{ i } " for i in range (len (args )))
211215 suffix = f", { arg_str } " if arg_str else ""
@@ -715,28 +719,32 @@ def generate(config_path, output_dir):
715719 "NSString" : "__ns_aot_return_string(info, {result})" ,
716720 "instancetype" : "__ns_aot_return_object(info, {result})" ,
717721 "BOOL" : "__ns_aot_return_bool(info, {result})" ,
718- "Class" : "__ns_aot_return_id (info, (id) {result})" ,
722+ "Class" : "__ns_aot_return_class (info, {result})" ,
719723}
720724
721725
722- def external_arg_expr (arg_type , i ):
726+ def external_arg_expr (arg_type , i , object_types = frozenset () ):
723727 if arg_type in EXTERNAL_ARG :
724728 return EXTERNAL_ARG [arg_type ].format (i = i )
729+ if arg_type in object_types :
730+ return EXTERNAL_ARG ["id" ].format (i = i )
725731 if arg_type in TYPES :
726732 return f"({ TYPES [arg_type ]['c_type' ]} )__ns_aot_arg_double(info, { i } )"
727733 return None
728734
729735
730- def is_struct_type (ret_type ):
731- return ret_type not in TYPES and ret_type not in EXTERNAL_RET
736+ def is_struct_type (ret_type , object_types = frozenset () ):
737+ return ret_type not in TYPES and ret_type not in EXTERNAL_RET and ret_type not in object_types
732738
733739
734- def external_ret_call (ret_type , result_var ):
740+ def external_ret_call (ret_type , result_var , object_types = frozenset () ):
735741 if ret_type == "void" :
736742 return None
737743 if ret_type in EXTERNAL_RET :
738744 return EXTERNAL_RET [ret_type ].format (result = result_var )
739- if is_struct_type (ret_type ):
745+ if ret_type in object_types :
746+ return EXTERNAL_RET ["id" ].format (result = result_var )
747+ if is_struct_type (ret_type , object_types ):
740748 return f'__ns_aot_return_struct(info, &{ result_var } , "{ ret_type } ")'
741749 return f"__ns_aot_return_double(info, (double){ result_var } )"
742750
@@ -745,18 +753,18 @@ def class_var_name(cls):
745753 return f"_cls_{ cls } "
746754
747755
748- def gen_external_method_stub (method , swift_classes ):
756+ def gen_external_method_stub (method , object_types = frozenset (), protocol_types = frozenset (), swift_classes = frozenset () ):
749757 cls = method ["class" ]
750758 sel = method ["selector" ]
751759 ret = method ["ret" ]
752760 args = method ["args" ]
753761 is_static = method .get ("static" , False )
754762 name = method_stub_name (cls , sel )
755763 is_void = ret == "void"
756- is_struct = is_struct_type ( ret )
757- c_ret_type = ret if is_struct else TYPES [ ret ][ "c_type" ]
758- is_swift = cls in swift_classes
759- cvar = class_var_name ( cls ) if is_swift else None
764+ is_obj = ret in object_types
765+ is_struct = is_struct_type ( ret , object_types )
766+ c_ret_type = "id" if is_obj else ( ret if is_struct else TYPES [ ret ][ "c_type" ])
767+ needs_msgsend = cls in protocol_types or cls in swift_classes
760768
761769 sign = "+" if is_static else "-"
762770 lines = []
@@ -772,9 +780,9 @@ def gen_external_method_stub(method, swift_classes):
772780 lines .append (" if (target == nil) return;" )
773781
774782 for i , arg in enumerate (args ):
775- expr = external_arg_expr (arg , i )
783+ expr = external_arg_expr (arg , i , object_types )
776784 if expr is not None :
777- c_type = TYPES [arg ]['c_type' ] if arg in TYPES else arg
785+ c_type = "id" if arg in object_types else ( TYPES [arg ]['c_type' ] if arg in TYPES else arg )
778786 lines .append (f" { c_type } arg{ i } = { expr } ;" )
779787 else :
780788 lines .append (f" { arg } arg{ i } ;" )
@@ -785,14 +793,17 @@ def gen_external_method_stub(method, swift_classes):
785793 lines .append (f" { c_ret_type } result;" )
786794
787795 if is_static :
788- static_call = _build_msgsend_call ("_cls" , sel , ret , args )
796+ static_call = _build_msgsend_call ("_cls" , sel , ret , args , object_types )
789797 if is_void :
790798 lines .append (f" { static_call } ;" )
791799 else :
792800 lines .append (f" result = { static_call } ;" )
793801 else :
794- objc_call = build_objc_call (cls , sel , args , is_static = False , class_var = cvar , ret = ret )
795- super_call = build_super_call (cls , sel , ret , args , struct_tag = True )
802+ if needs_msgsend :
803+ objc_call = _build_msgsend_call ("target" , sel , ret , args , object_types )
804+ else :
805+ objc_call = build_objc_call (cls , sel , args , is_static = False , ret = ret , object_types = object_types )
806+ super_call = build_super_call (cls , sel , ret , args , struct_tag = True , object_types = object_types )
796807 lines .append (" if (callSuper) {" )
797808 lines .append (" struct objc_super sup = {target, class_getSuperclass(object_getClass(target))};" )
798809 if is_void :
@@ -806,7 +817,7 @@ def gen_external_method_stub(method, swift_classes):
806817 lines .append (f" result = { objc_call } ;" )
807818 lines .append (" }" )
808819
809- ret_call = external_ret_call (ret , "result" )
820+ ret_call = external_ret_call (ret , "result" , object_types )
810821 if ret_call :
811822 lines .append (f" { ret_call } ;" )
812823
@@ -878,6 +889,8 @@ def generate_external(config_path, output_path):
878889 methods = _dedup_methods (config .get ("methods" , []))
879890 imports = config .get ("imports" , [])
880891 swift_classes = set (config .get ("swiftClasses" , []))
892+ object_types = frozenset (config .get ("objectTypes" , []))
893+ protocol_types = frozenset (config .get ("protocolTypes" , []))
881894
882895 extra_imports = [i if i .startswith ("#" ) else f"#import <{ i } /{ i } .h>" for i in imports ]
883896 if extra_imports :
@@ -890,7 +903,7 @@ def generate_external(config_path, output_path):
890903 parts .append ("" )
891904
892905 for m in methods :
893- parts .append (gen_external_method_stub (m , swift_classes ))
906+ parts .append (gen_external_method_stub (m , object_types , protocol_types , swift_classes ))
894907 parts .append ("" )
895908
896909 parts .append (gen_external_registration (methods , swift_classes ))
0 commit comments