mirror of https://github.com/kivy/pyobjus.git
Added support for varargs methods! I have tested this with arrayWithObjects method, and it works OK. Last argument must be nil in objective c, and in python we need to pass None insted of nil. Later internally in pyobjus, None is convered to NULL, otherwise we are getting segmentation fault
This commit is contained in:
parent
ce5e0ce772
commit
5f58c2b1ac
|
@ -2,8 +2,6 @@
|
||||||
#include <objc/objc-runtime.h>
|
#include <objc/objc-runtime.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <Python.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
static void pyobjc_internal_init() {
|
static void pyobjc_internal_init() {
|
||||||
static void *foundation = NULL;
|
static void *foundation = NULL;
|
||||||
|
|
|
@ -10,7 +10,6 @@ include "common.pxi"
|
||||||
include "runtime.pxi"
|
include "runtime.pxi"
|
||||||
include "ffi.pxi"
|
include "ffi.pxi"
|
||||||
include "type_enc.pxi"
|
include "type_enc.pxi"
|
||||||
from ctypes import c_void_p
|
|
||||||
from debug import dprint
|
from debug import dprint
|
||||||
|
|
||||||
# do the initialization!
|
# do the initialization!
|
||||||
|
@ -111,12 +110,16 @@ cdef class ObjcMethod(object):
|
||||||
cdef int is_static
|
cdef int is_static
|
||||||
cdef object signature_return
|
cdef object signature_return
|
||||||
cdef object signature_args
|
cdef object signature_args
|
||||||
|
# this attribute is required for pyobjus varargs implementation
|
||||||
|
cdef object signature_default_args
|
||||||
cdef Class o_cls
|
cdef Class o_cls
|
||||||
cdef id o_instance
|
cdef id o_instance
|
||||||
cdef SEL selector
|
cdef SEL selector
|
||||||
cdef SEL *selectors
|
cdef SEL *selectors
|
||||||
cdef ObjcClassInstance p_class
|
cdef ObjcClassInstance p_class
|
||||||
|
cdef int is_varargs
|
||||||
|
cdef object a
|
||||||
|
cdef object b
|
||||||
cdef int is_ready
|
cdef int is_ready
|
||||||
cdef ffi_cif f_cif
|
cdef ffi_cif f_cif
|
||||||
cdef ffi_type* f_result_type
|
cdef ffi_type* f_result_type
|
||||||
|
@ -129,6 +132,7 @@ cdef class ObjcMethod(object):
|
||||||
self.name = None
|
self.name = None
|
||||||
self.selector = NULL
|
self.selector = NULL
|
||||||
self.selectors = NULL
|
self.selectors = NULL
|
||||||
|
self.is_varargs = 0
|
||||||
|
|
||||||
def __dealloc__(self):
|
def __dealloc__(self):
|
||||||
self.is_ready = 0
|
self.is_ready = 0
|
||||||
|
@ -199,7 +203,6 @@ cdef class ObjcMethod(object):
|
||||||
|
|
||||||
self.is_ready = 1
|
self.is_ready = 1
|
||||||
|
|
||||||
|
|
||||||
def __get__(self, obj, objtype):
|
def __get__(self, obj, objtype):
|
||||||
if obj is None:
|
if obj is None:
|
||||||
return self
|
return self
|
||||||
|
@ -207,11 +210,35 @@ cdef class ObjcMethod(object):
|
||||||
self.o_instance = oc.o_instance
|
self.o_instance = oc.o_instance
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __call__(self, *args):
|
def __call__(self, *args, **kwargs):
|
||||||
#if self.is_static:
|
if len(args) > (len(self.signature_args) - 2):
|
||||||
# return self._call_class_method(*args)
|
dprint("preparing potential varargs method...", type='i')
|
||||||
|
self.is_varargs = True
|
||||||
|
self.is_ready = False
|
||||||
|
|
||||||
|
# we are substracting 2 because first two arguments are selector and self
|
||||||
|
self.signature_default_args = self.signature_args[:]
|
||||||
|
num_of_signature_args = len(self.signature_args) - 2
|
||||||
|
num_of_passed_args = len(args)
|
||||||
|
num_of_arguments_to_add = num_of_passed_args - num_of_signature_args
|
||||||
|
|
||||||
|
for i in range(num_of_arguments_to_add):
|
||||||
|
self.signature_args.append(self.signature_args[-1])
|
||||||
|
|
||||||
|
# we need prepare new number of arguments for ffi_call
|
||||||
|
self.ensure_method()
|
||||||
return self._call_instance_method(*args)
|
return self._call_instance_method(*args)
|
||||||
|
|
||||||
|
def _reset_method_attributes(self):
|
||||||
|
'''Method for setting adapted attributes values to default ones
|
||||||
|
'''
|
||||||
|
dprint("reseting method attributes...", type='i')
|
||||||
|
self.signature_args = self.signature_default_args
|
||||||
|
self.is_ready = False
|
||||||
|
self.ensure_method()
|
||||||
|
# this is little optimisation in case of calling varargs method multiple times with None as argument
|
||||||
|
self.is_varargs = False
|
||||||
|
|
||||||
def _call_instance_method(self, *args):
|
def _call_instance_method(self, *args):
|
||||||
|
|
||||||
dprint('-' * 80)
|
dprint('-' * 80)
|
||||||
|
@ -221,13 +248,11 @@ cdef class ObjcMethod(object):
|
||||||
dprint('--> return def is', self.signature_return)
|
dprint('--> return def is', self.signature_return)
|
||||||
dprint('--> args def is', self.signature_args)
|
dprint('--> args def is', self.signature_args)
|
||||||
|
|
||||||
|
|
||||||
cdef ffi_arg f_result
|
cdef ffi_arg f_result
|
||||||
cdef void **f_args
|
cdef void **f_args
|
||||||
cdef int index
|
cdef int index
|
||||||
cdef size_t size
|
cdef size_t size
|
||||||
cdef ObjcClassInstance arg_objcclass
|
cdef ObjcClassInstance arg_objcclass
|
||||||
|
|
||||||
# allocate f_args
|
# allocate f_args
|
||||||
f_args = <void**>malloc(sizeof(void *) * len(self.signature_args))
|
f_args = <void**>malloc(sizeof(void *) * len(self.signature_args))
|
||||||
if f_args == NULL:
|
if f_args == NULL:
|
||||||
|
@ -275,6 +300,9 @@ cdef class ObjcMethod(object):
|
||||||
(<char **>val_ptr)[0] = <char *><bytes>arg
|
(<char **>val_ptr)[0] = <char *><bytes>arg
|
||||||
elif sig == '@':
|
elif sig == '@':
|
||||||
dprint('====> ARG', <ObjcClassInstance>arg)
|
dprint('====> ARG', <ObjcClassInstance>arg)
|
||||||
|
if arg == None:
|
||||||
|
(<id*>val_ptr)[0] = <id>NULL
|
||||||
|
else:
|
||||||
ocl = <ObjcClassInstance>arg
|
ocl = <ObjcClassInstance>arg
|
||||||
(<id*>val_ptr)[0] = <id>ocl.o_instance
|
(<id*>val_ptr)[0] = <id>ocl.o_instance
|
||||||
# method is accepting class
|
# method is accepting class
|
||||||
|
@ -301,6 +329,9 @@ cdef class ObjcMethod(object):
|
||||||
|
|
||||||
sig = self.signature_return[0]
|
sig = self.signature_return[0]
|
||||||
dprint("return signature", sig, type="i")
|
dprint("return signature", sig, type="i")
|
||||||
|
if self.is_varargs:
|
||||||
|
self._reset_method_attributes()
|
||||||
|
|
||||||
cdef id ret_id
|
cdef id ret_id
|
||||||
cdef ObjcClassInstance cret
|
cdef ObjcClassInstance cret
|
||||||
cdef bytes bret
|
cdef bytes bret
|
||||||
|
|
|
@ -53,3 +53,16 @@ print array.retainCount()
|
||||||
array.release()
|
array.release()
|
||||||
print array.retainCount()
|
print array.retainCount()
|
||||||
|
|
||||||
|
array_test = NSArray.arrayWithObjects_(text, newText, text, array, None)
|
||||||
|
print array_test.count()
|
||||||
|
|
||||||
|
array_new = NSArray.arrayWithObjects_(text, newText, None)
|
||||||
|
array_new = NSArray.arrayWithObjects_(None)
|
||||||
|
print array_new.count()
|
||||||
|
array_new = NSArray.arrayWithObjects_(None)
|
||||||
|
array_new = NSArray.arrayWithObjects_(text, None)
|
||||||
|
array_new = NSArray.alloc().initWithObjects_(None)
|
||||||
|
array_new = NSArray.alloc().initWithObjects_(text, None)
|
||||||
|
print array_new.objectAtIndex_(0).UTF8String()
|
||||||
|
array_new = NSArray.alloc().initWithObjects_(None)
|
||||||
|
print array_new.count()
|
||||||
|
|
Loading…
Reference in New Issue