diff --git a/examples/ClassesAndSelectors.py b/examples/classes_and_selectors.py similarity index 100% rename from examples/ClassesAndSelectors.py rename to examples/classes_and_selectors.py diff --git a/examples/NSAlert.py b/examples/ns_alert.py similarity index 100% rename from examples/NSAlert.py rename to examples/ns_alert.py diff --git a/examples/NSArray.py b/examples/ns_array.py similarity index 100% rename from examples/NSArray.py rename to examples/ns_array.py diff --git a/examples/NSDictionary.py b/examples/ns_dictionary.py similarity index 100% rename from examples/NSDictionary.py rename to examples/ns_dictionary.py diff --git a/examples/NSMutableArray.py b/examples/ns_mutable_array.py similarity index 100% rename from examples/NSMutableArray.py rename to examples/ns_mutable_array.py diff --git a/examples/NSMutableDictionary.py b/examples/ns_mutable_dictionary.py similarity index 100% rename from examples/NSMutableDictionary.py rename to examples/ns_mutable_dictionary.py diff --git a/pyobjus/_runtime.h b/pyobjus/_runtime.h index 83e1d24..a0949e6 100644 --- a/pyobjus/_runtime.h +++ b/pyobjus/_runtime.h @@ -2,8 +2,6 @@ #include #include #include -#include -#include static void pyobjc_internal_init() { static void *foundation = NULL; diff --git a/pyobjus/pyobjus.pyx b/pyobjus/pyobjus.pyx index 784f361..005383d 100644 --- a/pyobjus/pyobjus.pyx +++ b/pyobjus/pyobjus.pyx @@ -10,7 +10,6 @@ include "common.pxi" include "runtime.pxi" include "ffi.pxi" include "type_enc.pxi" -from ctypes import c_void_p from debug import dprint # do the initialization! @@ -111,12 +110,16 @@ cdef class ObjcMethod(object): cdef int is_static cdef object signature_return cdef object signature_args + # this attribute is required for pyobjus varargs implementation + cdef object signature_default_args cdef Class o_cls cdef id o_instance cdef SEL selector cdef SEL *selectors cdef ObjcClassInstance p_class - + cdef int is_varargs + cdef object a + cdef object b cdef int is_ready cdef ffi_cif f_cif cdef ffi_type* f_result_type @@ -129,6 +132,7 @@ cdef class ObjcMethod(object): self.name = None self.selector = NULL self.selectors = NULL + self.is_varargs = 0 def __dealloc__(self): self.is_ready = 0 @@ -199,7 +203,6 @@ cdef class ObjcMethod(object): self.is_ready = 1 - def __get__(self, obj, objtype): if obj is None: return self @@ -207,11 +210,35 @@ cdef class ObjcMethod(object): self.o_instance = oc.o_instance return self - def __call__(self, *args): - #if self.is_static: - # return self._call_class_method(*args) + def __call__(self, *args, **kwargs): + if len(args) > (len(self.signature_args) - 2): + 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) + 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): dprint('-' * 80) @@ -220,14 +247,12 @@ cdef class ObjcMethod(object): dprint('--> want to call', self.name, args) dprint('--> return def is', self.signature_return) dprint('--> args def is', self.signature_args) - cdef ffi_arg f_result cdef void **f_args cdef int index cdef size_t size cdef ObjcClassInstance arg_objcclass - # allocate f_args f_args = malloc(sizeof(void *) * len(self.signature_args)) if f_args == NULL: @@ -254,7 +279,7 @@ cdef class ObjcMethod(object): for index in range(2, len(self.signature_args)): # argument passed to call arg = args[index-2] - + # we already know the ffitype/size being used val_ptr = malloc(self.f_arg_types[index][0].size) dprint("index {}: allocating {} bytes for arg: {!r}".format( @@ -275,8 +300,11 @@ cdef class ObjcMethod(object): (val_ptr)[0] = arg elif sig == '@': dprint('====> ARG', arg) - ocl = arg - (val_ptr)[0] = ocl.o_instance + if arg == None: + (val_ptr)[0] = NULL + else: + ocl = arg + (val_ptr)[0] = ocl.o_instance # method is accepting class elif sig == '#': dprint('===> Class arg', arg) @@ -296,11 +324,14 @@ cdef class ObjcMethod(object): f_args[f_index] = val_ptr dprint('pointer before ffi_call:', pr(f_args[f_index])) - + ffi_call(&self.f_cif, objc_msgSend, &f_result, f_args) sig = self.signature_return[0] dprint("return signature", sig, type="i") + if self.is_varargs: + self._reset_method_attributes() + cdef id ret_id cdef ObjcClassInstance cret cdef bytes bret diff --git a/pyobjus/test.py b/pyobjus/test.py index 64e3a9e..35945c2 100644 --- a/pyobjus/test.py +++ b/pyobjus/test.py @@ -53,3 +53,16 @@ print array.retainCount() array.release() 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()