예제 #1
0
    def swizzled(self, sel, *args):
        print('{}:{} called'.format(time.ctime(), method))
        print(args)
        argtypes = parse_types(
            ObjCInstanceMethod(ObjCInstance(self), method).encoding)[1][2:]
        newargs = []
        for a, ty in zip(args, argtypes):
            if a is not None and ty is c_void_p:

                def p():
                    print(ObjCInstance(a))

                ui.delay(p, 1)
                newargs.append(a)
            else:

                def p():
                    print(a)

                ui.delay(p, 1)
                newargs.append(a)
        returnval = ObjCInstanceMethod(ObjCInstance(self),
                                       'original' + method)(*newargs)
        print('returnval', returnval)
        if isinstance(returnval, ObjCInstance):
            return returnval.ptr
        else:
            return returnval
예제 #2
0
def swizzle(cls, old_sel, new_fcn):
    '''swizzles cls.old_sel with new_fcn.  Assumes encoding is the same.
    if class already has swizzledSelector, unswizzle first.
    original selector can be called via originalSelectir
    
    '''
    orig_method=c.class_getInstanceMethod(cls.ptr, sel(old_sel))
    #new_method=c.class_getInstanceMethod(cls, sel(new_sel))
    type_encoding=str(cls.instanceMethodSignatureForSelector_(sel(old_sel))._typeString())
    parsed_types = parse_types(str(type_encoding))
    restype = parsed_types[0]
    argtypes = parsed_types[1]
    # Check if the number of arguments derived from the selector matches the actual function:
    argspec = inspect.getargspec(new_fcn)
    if len(argspec.args) != len(argtypes):
        raise ValueError('%s has %i arguments (expected %i)' % (method, len(argspec.args), len(argtypes)))
    IMPTYPE = ctypes.CFUNCTYPE(restype, *argtypes)
    imp = IMPTYPE(new_fcn)
    retain_global(imp)
    new_sel='_original'+old_sel
    didAdd=c.class_addMethod(cls.ptr, sel(new_sel), imp, type_encoding)
    new_method=c.class_getInstanceMethod(cls.ptr, sel(new_sel))
    # swap imps
    c.method_exchangeImplementations.restype=None
    c.method_exchangeImplementations.argtypes=[c_void_p,c_void_p]
    c.method_exchangeImplementations(orig_method, new_method)
    return new_sel
예제 #3
0
def swizzle(cls_name, selector_name, fn):
    cls = ObjCClass(cls_name).ptr

    new_selector_name = SWIZZLED_SELECTOR_PREFIX + selector_name
    new_selector = sel(new_selector_name)

    if c.class_getInstanceMethod(cls, new_selector):
        error('Skipping swizzling, already responds to {} selector'.format(
            new_selector_name))
        return

    selector = sel(selector_name)
    method = c.class_getInstanceMethod(cls, selector)
    if not method:
        error('Failed to get {} instance method'.format(selector_name))
        return

    type_encoding = c.method_getTypeEncoding(method)
    parsed_types = parse_types(type_encoding)
    restype = parsed_types[0]
    argtypes = parsed_types[1]

    IMPTYPE = CFUNCTYPE(restype, *argtypes)
    imp = IMPTYPE(fn)
    retain_global(imp)

    did_add = c.class_addMethod(cls, new_selector, imp, type_encoding)

    if not did_add:
        error('Failed to add {} method'.format(new_selector_name))
        return

    new_method = c.class_getInstanceMethod(cls, new_selector)
    method_exchangeImplementations(method, new_method)
예제 #4
0
def add_method(cls_name, selector_name, fn, type_encoding):
    cls = ObjCClass(cls_name).ptr

    selector = sel(selector_name)

    if c.class_getInstanceMethod(cls, selector):
        error(
            'Failed to add method, class {} already provides method {}'.format(
                cls_name, selector_name))
        return

    parsed_types = parse_types(type_encoding)
    restype = parsed_types[0]
    argtypes = parsed_types[1]

    IMPTYPE = CFUNCTYPE(restype, *argtypes)
    imp = IMPTYPE(fn)
    retain_global(imp)

    did_add = c.class_addMethod(cls, selector, imp,
                                c_char_p(type_encoding.encode('utf-8')))
    if not did_add:
        error('Failed to add class method')

    return did_add
예제 #5
0
def swizzle(cls, selector, new_fcn,type_encoding=None):
	'''swizzles ObjCClass cls's selector with implementation from python new_fcn.  new_fcn needs to adjere to ther type encoding of the original, including the two "hidden" arguments _self, _sel.

	if a class is already swizzled, this will override swizzled implemetation, and use new method.  We could implement a forwarding system, but it becomes hard to unswizzle because there is no way to remove a selector once added.  
	
	A method can always get its predecessor by simply prepending original to its selector name.
	
	If the referenced method does not exist, must supply type_encoding.
	
	'''

	if not type_encoding:				
		type_encoding=_str_to_bytes(str(cls.instanceMethodSignatureForSelector_(sel(selector))._typeString()))
	else:
		type_encoding=_str_to_bytes(type_encoding)
	parsed_types = parse_types(_str_to_bytes(type_encoding))
	restype = parsed_types[0]
	argtypes = parsed_types[1]
	# Check if the number of arguments derived from the selector matches the actual function:

	try:
		argspec=inspect.getargspec(new_fcn.__closure__[0].cell_contents)
	except:
		argspec = inspect.getargspec(new_fcn)
	if len(argspec.args) != len(argtypes):
		raise ValueError('%s has %i arguments (expected %i)' % (new_fcn, len(argspec.args), len(argtypes)))
	IMPTYPE = ctypes.CFUNCTYPE(restype, *argtypes)
	imp = IMPTYPE(new_fcn)
	retain_global(imp)
	
	#find rootmost parent
	# add new to orig_....   N (N-3) (N-2) (N-1)
	# then starting at end, swap up the chain
	if not c.class_getInstanceMethod(cls.ptr, sel(selector)):
		# just add the selector
		new_sel = selector
		didAdd=c.class_addMethod(cls.ptr, sel(new_sel), imp, (type_encoding))
		return
	
	new_sel = 'original'+selector
	didAdd=c.class_addMethod(cls.ptr, sel(new_sel), imp, (type_encoding))

	method_exchangeImplementations=c.method_exchangeImplementations
	method_exchangeImplementations.restype=None
	method_exchangeImplementations.argtypes=[c_void_p,c_void_p]
	
	method_setImplementation=c.method_setImplementation
	method_setImplementation.restype=None
	method_setImplementation.argtypes=[c_void_p, c_void_p]
	if didAdd:
			orig_method=c.class_getInstanceMethod(cls.ptr, sel(selector))
			new_method=c.class_getInstanceMethod(cls.ptr, sel(new_sel))
			method_exchangeImplementations(orig_method, new_method)
	else:
		# setimp, 
		orig_method=c.class_getInstanceMethod(cls.ptr, sel(selector))
		method_setImplementation(orig_method,imp)
예제 #6
0
    def swizzled(self, sel, *args):
        with Lock():
            logger.debug('# # # # # {} # # # # #'.format(method))
            logger.debug('   self:{}'.format(self))
            logger.debug('   args:{}'.format(args))
            argtypes = parse_types(
                ObjCInstanceMethod(ObjCInstance(self), method).encoding)[1][2:]
            newargs = []
            argidx = 0
            for a, ty in zip(args, argtypes):
                argidx += 1
                if a is not None and ty is c_void_p:
                    logger.debug('    {}\n       {}\n      {}'.format(
                        argidx, ObjCInstance(a), ty))
                    newargs.append(ObjCInstance(a))
                elif a is not None and ty is ObjCBlock:

                    def block_logger(_cmd, requestid, matches):
                        logger.debug(
                            '__logger_block: call to {}({}). args: {}, {}'.
                            format(ObjCInstance(a), _cmd, requestid, matches))

                        #logger.debug('{}'.format(signature))
                        #invoke=cast(bb.ptr,POINTER(block_literal)).contents.invoke
                        #invoke(_cmd, requestid, matches)

                    blk = ObjCBlock(block_logger,
                                    restype=None,
                                    argtypes=[c_void_p, c_int, c_void_p])
                    newargs.append(blk)
                else:
                    logger.debug('    {}\n       {}\n     {}'.format(
                        argidx, (a), ty))
                    #ui.delay(p,1)
                    newargs.append(a)
            selfinstance = ObjCInstance(self)
            logger.debug(('self=', selfinstance))
            try:
                originalmethod = ObjCInstanceMethod(ObjCInstance(self),
                                                    'original' + method)
                #logger.debug(originalmethod)
            except AttributeError:
                import console
                console.hud_alert(method)
                logger.debug('     attrib error, returning none')
                return None
            if originalmethod:
                logger.debug(('     newargs', newargs))
                returnval = originalmethod(*newargs)
                logger.debug(('  =====>', returnval))
            if isinstance(returnval, ObjCInstance):
                return returnval.ptr
            else:
                return returnval
예제 #7
0
def _add_method(cls, func):
    # void, object, selector
    type_encoding = "v@:"
    sel_name = str(uuid.uuid4())
    sel = objc_util.sel(sel_name)
    class_ptr = objc_util.object_getClass(cls.ptr)

    # ----------------- Modified from objc_util.add_method ------------------ #
    parsed_types = objc_util.parse_types(type_encoding)
    restype, argtypes, _ = parsed_types
    imp = ctypes.CFUNCTYPE(restype, *argtypes)(func)
    objc_util.retain_global(imp)
    if isinstance(type_encoding, str):
        type_encoding = type_encoding.encode('ascii')
    objc_util.class_addMethod(class_ptr, sel, imp, type_encoding)
    # ----------------------------------------------------------------------- #
    return sel
예제 #8
0
def swizzle(cls, selector, new_fcn):
    '''swizzles ObjCClass cls's selector with implementation from python new_fcn.  new_fcn needs to adhere to the type encoding of the original, including the two "hidden" arguments _self, _sel.

	if a class is already swizzled, this will override swizzled implementation, and use new method.  We could implement a forwarding system, but it becomes hard to unswizzle because there is no way to remove a selector once added.  
	
	A method can always get its predecessor by simply prepending original to its selector name.
	'''
    type_encoding = str(
        cls.instanceMethodSignatureForSelector_(sel(selector))._typeString())
    parsed_types = parse_types(str(type_encoding))
    restype = parsed_types[0]
    argtypes = parsed_types[1]
    # Check if the number of arguments derived from the selector matches the actual function:
    argspec = inspect.getargspec(new_fcn)
    if len(argspec.args) != len(argtypes):
        raise ValueError('%s has %i arguments (expected %i)' %
                         (method, len(argspec.args), len(argtypes)))
    IMPTYPE = ctypes.CFUNCTYPE(restype, *argtypes)
    imp = IMPTYPE(new_fcn)
    retain_global(imp)

    #find rootmost parent
    # add new to orig_....   N (N-3) (N-2) (N-1)
    # then starting at end, swap up the chain
    if not c.class_getInstanceMethod(cls.ptr, sel(selector)):
        return

    new_sel = 'original' + selector
    didAdd = c.class_addMethod(cls.ptr, sel(new_sel), imp, type_encoding)

    method_exchangeImplementations = c.method_exchangeImplementations
    method_exchangeImplementations.restype = None
    method_exchangeImplementations.argtypes = [c_void_p, c_void_p]

    method_setImplementation = c.method_setImplementation
    method_setImplementation.restype = None
    method_setImplementation.argtypes = [c_void_p, c_void_p]
    if didAdd:
        orig_method = c.class_getInstanceMethod(cls.ptr, sel(selector))
        new_method = c.class_getInstanceMethod(cls.ptr, sel(new_sel))
        method_exchangeImplementations(orig_method, new_method)
    else:
        # setimp,
        orig_method = c.class_getInstanceMethod(cls.ptr, sel(selector))
        method_setImplementation(orig_method, imp)
예제 #9
0
def add_method(method, cls):
	guard_objc_util()
	import ctypes
	import objc_util
	import uuid
	
	encoding = "v@:"
	
	# this code is borrowed from `objc_util._add_method`
	parsed_types = objc_util.parse_types(encoding)
	restype = parsed_types[0]
	argtypes = parsed_types[1]
	IMPTYPE = ctypes.CFUNCTYPE(restype, *argtypes)
	imp = IMPTYPE(method)
	objc_util.retain_global(imp)
	
	selector = objc_util.sel(str(uuid.uuid1()).replace("-", ""))
	objc_util.class_addMethod(objc_util.object_getClass(cls.ptr), selector, imp, encoding.encode("ascii"))
	return selector
예제 #10
0
	def swizzled(self,sel,*args):
		print('{}:{} called'.format(time.ctime(),method))
		print (args)
		argtypes=parse_types(ObjCInstanceMethod(ObjCInstance(self), method).encoding)[1][2:]
		newargs=[]
		for a,ty in zip(args,argtypes):
			if a is not None and ty is c_void_p:
				def p():
					print (ObjCInstance(a))
				ui.delay(p,1)
				newargs.append(a)
			else:
				def p():
					print(a)
				ui.delay(p,1)
				newargs.append(a)
		returnval= ObjCInstanceMethod(ObjCInstance(self), 'original'+method)(*newargs)
		print('returnval',returnval)
		if isinstance(returnval,ObjCInstance):
			return returnval.ptr
		else:
			return returnval
예제 #11
0
def swizzle(cls, selector, new_fcn, type_encoding=None, debug=False):
    '''swizzles ObjCClass cls's selector with implementation from python new_fcn.  new_fcn needs to adjere to ther type encoding of the original, including the two "hidden" arguments _self, _sel.

	if a class is already swizzled, this will override swizzled implemetation, and use new method.  We could implement a forwarding system, but it becomes hard to unswizzle because there is no way to remove a selector once added.  
	
	A method can always get its predecessor by simply prepending original to its selector name.
	
	If the referenced method does not exist, must supply type_encoding.
	
	'''

    if not type_encoding:
        type_encoding = _str_to_bytes(
            str(
                cls.instanceMethodSignatureForSelector_(
                    sel(selector))._typeString()))
    else:
        type_encoding = _str_to_bytes(type_encoding)
    parsed_types = parse_types(_str_to_bytes(type_encoding))
    restype = parsed_types[0]
    argtypes = parsed_types[1]
    # Check if the number of arguments derived from the selector matches the actual function:

    try:
        argspec = inspect.getargspec(new_fcn.__closure__[0].cell_contents)
    except:
        argspec = inspect.getargspec(new_fcn)
    has_varargs = inspect.getargspec(new_fcn).varargs
    if (len(argspec.args) != len(argtypes)) and not has_varargs:
        raise ValueError('%s has %i arguments (expected %i)' %
                         (new_fcn, len(argspec.args), len(argtypes)))
    for i, arg in enumerate(argtypes):
        if arg == ObjCBlock:
            if debug: print('replace block with voidp')
            argtypes[i] = ctypes.c_void_p
    IMPTYPE = ctypes.CFUNCTYPE(restype, *argtypes)
    imp = IMPTYPE(new_fcn)
    retain_global(imp)
    if debug:
        print(restype)
        print(argtypes)
        print(selector)
        print(cls)
    #find rootmost parent
    # add new to orig_....   N (N-3) (N-2) (N-1)
    # then starting at end, swap up the chain
    if not c.class_getInstanceMethod(cls.ptr, sel(selector)):
        # just add the selector
        new_sel = selector
        didAdd = c.class_addMethod(cls.ptr, sel(new_sel), imp, (type_encoding))
        return

    new_sel = 'original' + selector
    didAdd = c.class_addMethod(cls.ptr, sel(new_sel), imp, (type_encoding))

    method_exchangeImplementations = c.method_exchangeImplementations
    method_exchangeImplementations.restype = None
    method_exchangeImplementations.argtypes = [c_void_p, c_void_p]

    method_setImplementation = c.method_setImplementation
    method_setImplementation.restype = None
    method_setImplementation.argtypes = [c_void_p, c_void_p]
    if didAdd:
        orig_method = c.class_getInstanceMethod(cls.ptr, sel(selector))
        new_method = c.class_getInstanceMethod(cls.ptr, sel(new_sel))
        method_exchangeImplementations(orig_method, new_method)
    else:
        # setimp,
        orig_method = c.class_getInstanceMethod(cls.ptr, sel(selector))
        method_setImplementation(orig_method, imp)