@@ -878,6 +878,9 @@ cdef void protocol_forwardInvocation(id self, SEL _cmd, id invocation) with gil:
878878 cls_name = class_getName(cls )
879879 for i in range (2 , signature.numberOfArguments):
880880 tp = signature.getArgumentTypeAtIndex_(i)
881+ if isinstance (tp, unicode ):
882+ tp = tp.encode(' utf8' )
883+ tp = clean_type_specifier(tp)
881884 dprint(" pfi: argument type at {}: {}" .format(i, tp))
882885 arg_type = type_encoding_to_ffitype(tp[:1 ])
883886 dprint(' pfi: convert arg {} with type {}' .format(i, tp[:1 ]))
@@ -898,16 +901,15 @@ cdef void protocol_forwardInvocation(id self, SEL _cmd, id invocation) with gil:
898901 py_method = getattr (delegate, py_method_name)
899902 py_ret = py_method(* py_method_args)
900903
901- # Return type from the @protocol encoding (first char). Prefer the live
902- # NSInvocation signature so setReturnValue: size always matches what
903- # methodSignatureForSelector: advertised (including after a cache refresh
904- # when runtime CGFloat encodings replace a stale float fallback).
904+ # Return type from the live NSInvocation signature (preferred) or the
905+ # @protocol encoding. Strip ObjC type qualifiers (r/n/N/o/O/R/V) before
906+ # selecting the kind, consistent with clean_type_specifier elsewhere.
905907 kind = b' v'
906908 ret_tp = signature.methodReturnType
907909 if ret_tp is not None :
908- kind = ret_tp[: 1 ]
909- if isinstance (kind, unicode ):
910- kind = kind.encode( ' utf8 ' )
910+ if isinstance ( ret_tp, unicode ):
911+ ret_tp = ret_tp.encode( ' utf8 ' )
912+ kind = clean_type_specifier(ret_tp)[: 1 ]
911913 elif py_method is not None and hasattr (py_method, ' __protocol__' ):
912914 sel_name = sel_getName(_cmd).decode(' utf8' )
913915 d = objc_protocol_get_delegates(py_method.__protocol__)
@@ -916,13 +918,16 @@ cdef void protocol_forwardInvocation(id self, SEL _cmd, id invocation) with gil:
916918 enc = sigs[- 1 ]
917919 if isinstance (enc, unicode ):
918920 enc = enc.encode(' utf8' )
919- kind = enc[:1 ]
921+ kind = clean_type_specifier( enc) [:1 ]
920922 if kind == b' v' :
921923 return
922924 if kind == b' @' :
923925 obj = convert_py_to_nsobject(py_ret) if py_ret is not None else None
924926 ret_id = (< ObjcClassInstance> obj).o_instance if obj is not None else < id > NULL
925927 if ret_id != NULL :
928+ # Keep the returned object alive across the NSInvocation handoff.
929+ # CoreFoundation is linked on macOS by default; on iOS setup.py
930+ # adds -framework CoreFoundation.
926931 CFRetain(< void * > ret_id)
927932 CFAutorelease(< void * > ret_id)
928933 inv.setReturnValue_(< unsigned long long > & ret_id)
0 commit comments