Merge branch 'misl6-fix/args-no-frame'

This commit is contained in:
Akshay Arora 2024-10-04 13:14:03 +05:30
commit 573bd69b85
3 changed files with 37 additions and 53 deletions

View File

@ -93,8 +93,9 @@ cdef extern from "objc/runtime.h":
const_char_ptr sel_getName(SEL)
SEL method_getName(Method)
const_char_ptr method_getTypeEncoding(Method)
unsigned int method_getNumberOfArguments(Method)
const_char_ptr method_copyArgumentType(Method method, int)
const_char_ptr method_copyReturnType(Method)
objc_method_description* method_getDescription(Method m)
Class object_getClass(id obj)

View File

@ -189,7 +189,6 @@ def convert_return_value(retval, clsname, methodname):
cdef class ObjcMethod(object):
cdef bytes name
cdef bytes signature
cdef int is_static
cdef object signature_return
cdef object signature_current_args
@ -211,7 +210,7 @@ cdef class ObjcMethod(object):
cdef ffi_type **f_arg_types
cdef object objc_name
def __cinit__(self, signature, objc_name, **kwargs):
def __cinit__(self, objc_name, signature_args, signature_return, **kwargs):
self.is_ready = 0
self.f_result_type = NULL
self.f_arg_types = NULL
@ -238,10 +237,12 @@ cdef class ObjcMethod(object):
#self.f_result_type = NULL
# TODO: Memory management
def __init__(self, bytes signature, bytes objc_name, **kwargs):
def __init__(self, bytes objc_name, signature_args, signature_return, **kwargs):
super(ObjcMethod, self).__init__()
self.signature = <bytes>signature
self.signature_return, self.signature_args = parse_signature(signature)
self.signature_args = [clean_type_specifier(sign_arg) for sign_arg in signature_args]
self.signature_return = clean_type_specifier(signature_return)
self.is_static = kwargs.get('static', False)
self.name = kwargs.get('name')
self.objc_name = objc_name
@ -272,8 +273,8 @@ cdef class ObjcMethod(object):
else:
self.name = self.objc_name
if self.signature_return[0].startswith((b'(', b'{')):
sig = self.signature_return[0]
if self.signature_return.startswith((b'(', b'{')):
sig = self.signature_return
self.return_type = sig[1:-1].split(b'=', 1)
self.selector = sel_registerName(<bytes>self.name)
@ -290,12 +291,12 @@ cdef class ObjcMethod(object):
dprint('signature: {}'.format(signature_args))
# resolve f_result_type
if self.signature_return[0].startswith(b'('):
if self.signature_return.startswith(b'('):
self.f_result_type = type_encoding_to_ffitype(
self.signature_return[0], str_in_union=True)
self.signature_return, str_in_union=True)
else:
self.f_result_type = type_encoding_to_ffitype(
self.signature_return[0])
self.signature_return)
# casting is needed here because otherwise we will get warning at compile
cdef unsigned int num_args = <unsigned int>len(signature_args)
@ -313,12 +314,12 @@ cdef class ObjcMethod(object):
# populate f_args_type array for FFI prep
cdef int index = 0
for arg in signature_args:
if arg[0].startswith(b'('):
if arg.startswith(b'('):
raise ObjcException(
'Currently passing unions as arguments by '
'value is not supported in pyobjus!')
dprint('argument ==>', arg, len(signature_args))
self.f_arg_types[index] = type_encoding_to_ffitype(arg[0])
self.f_arg_types[index] = type_encoding_to_ffitype(arg)
index = index + 1
# FFI PREP
@ -360,7 +361,6 @@ cdef class ObjcMethod(object):
cdef int index
cdef size_t size
cdef ObjcClassInstance arg_objcclass
cdef size_t result_size = <size_t>int(self.signature_return[1])
# check that we have at least the same number of arguments as the
# signature want (having more than expected could signify that the called
@ -405,7 +405,7 @@ cdef class ObjcMethod(object):
sig_index = -1
signature_args.append(signature_args[-1])
sig, offset, attr = sig_full = signature_args[sig_index]
sig = signature_args[sig_index]
arg_size = type_encoding_to_ffitype(sig).size
# we already know the ffitype/size being used
@ -435,7 +435,7 @@ cdef class ObjcMethod(object):
if res_ptr == NULL:
raise MemoryError('Unable to allocate res_ptr')
if not self.signature_return[0].startswith((b'(', b'{')):
if not self.signature_return.startswith((b'(', b'{')):
ffi_call(&self.f_cif, <void(*)() noexcept><id(*)(id, SEL)>objc_msgSend, res_ptr, f_args)
else:
@ -461,7 +461,7 @@ cdef class ObjcMethod(object):
size_ret = ctypes.sizeof(obj_ret)
stret = False
if self.signature_return[0].startswith((b'{', b'(')) and size_ret > 16:
if self.signature_return.startswith((b'{', b'(')) and size_ret > 16:
stret = True
if stret and MACOS_HAVE_OBJMSGSEND_STRET:
@ -490,8 +490,8 @@ cdef class ObjcMethod(object):
cdef ObjcClassInstance cret
cdef bytes bret
sig = self.signature_return[0]
dprint("return signature", self.signature_return[0], of_type="i")
sig = self.signature_return
dprint("return signature", self.signature_return, of_type="i")
if sig == b'@':
ret_id = (<id>res_ptr[0])
@ -529,10 +529,13 @@ cdef objc_method_to_py(Method method, main_cls_name, static=True):
'''
cdef char* method_name = <char*>sel_getName(method_getName(method))
cdef char* method_args = <char*>method_getTypeEncoding(method)
cdef unsigned int method_args_len = method_getNumberOfArguments(method)
cdef char* method_return_type = method_copyReturnType(method)
cdef list method_args_types = [method_copyArgumentType(method, i) for i in range(method_args_len)]
cdef basestring py_name = (<bytes>method_name).replace(b":", b"_").decode("utf-8")
return py_name, ObjcMethod(<bytes>method_args, method_name, static=static, main_cls_name=main_cls_name)
return py_name, ObjcMethod(method_name, method_args_types, method_return_type, static=static, main_cls_name=main_cls_name)
cdef class_get_methods(Class cls, static=False, main_cls_name=None):
cdef unsigned int index, num_methods
@ -605,7 +608,11 @@ cdef get_class_method(Class cls, char *name):
ObjcMethod instance
'''
cdef Method m_cls = class_getClassMethod(cls, sel_registerName(name))
return ObjcMethod(<bytes><char*>method_getTypeEncoding(m_cls), name, static=True, \
cdef unsigned int method_args_len = method_getNumberOfArguments(m_cls)
cdef char* method_return_type = method_copyReturnType(m_cls)
cdef list method_args_types = [method_copyArgumentType(m_cls, i) for i in range(method_args_len)]
return ObjcMethod(name, method_args_types, method_return_type, static=True, \
main_cls_name=class_getName(cls))
cdef resolve_super_class_methods(Class cls, instance_methods=True):

View File

@ -1,36 +1,12 @@
def seperate_encoding(sig):
c = sig[0][:1]
if c in b'rnNoORV':
sig = (sig[0][1:], sig[1], c)
else:
sig = (sig[0], sig[1], None)
def clean_type_specifier(sig):
"""
Clean up the type specifier for a function signature.
See: https://gcc.gnu.org/onlinedocs/gcc-5.3.0/gcc/Type-encoding.html
"""
if sig[:1] in b'rnNoORV':
return sig[1:]
return sig
def parse_signature(bytes signature):
parts = re.split(b'(\d+)', signature)[:-1]
signature_return = seperate_encoding(parts[0:2])
parts = parts[2:]
signature_args = [seperate_encoding(x) for x in zip(parts[0::2], parts[1::2])]
# reassembly for array
if b'[' in signature:
tmp_sig = []
arr_sig = b''
for item in signature_args:
if item[0].startswith(b'['):
arr_sig += item[0] + item[1]
elif item[0].endswith(b']'):
arr_sig += item[0]
tmp_sig.append((arr_sig, item[1], item[2]))
else:
tmp_sig.append(item)
signature_args = tmp_sig
return signature_return, signature_args
def signature_types_to_list(type_encoding):
type_enc_list = []
curvy_brace_count = 0