我有像这样的objc方法;
@ implementation of Class1
- (void)execute:(void (^)(Class2* target, NSUInteger idx))block
{
...
}
我想在python中使用这个execute方法,我已经构建了一个python objective-c桥接数据,它似乎正确地生成为:
<class name='Class1'>
<method selector='execute:'>
<arg function_pointer='true' type='@?' index='0'>
<arg type='@'/>
<arg type='I' type64='Q'/>
<retval type='v'/>
</arg>
</method>
但是当我定义这样的函数时:
def myFunc (dev, index):
// do something with dev
print("Hello")
并尝试将其用作块
class1_obj.execute_(myFunc)
Python将错误抛出为:
objc.BadPrototypeError: Objective-C expects 1 arguments, Python argument has 2 arguments for <unbound selector myFunc at 0x105b3a3f0>
我也试过lambda函数,没用。
我还尝试创建一个可调用的类:
>>> class myCallable(object):
... def __init__(self,name):
... print "Init"
... def __repr__(self):
... return "string init"
... def __call__(self, dev, index):
... # do something with dev
... print("hello")
但是python会抛出这样的错误:
TypeError: Sorry, cannot create IMP for instances of type myCallable
我想知道我在哪里做错了?
答案 0 :(得分:2)
感谢Josh的建议。
终于解决了这个问题。看起来系统使用命令行gen_bridge_metadata生成的meta_data无法正确读取。它生成为:
<method selector='execute:'>
<arg index='0' type='@?' function_pointer='true'>
<arg type='@'/>
<arg type64='Q' type='I'/>
<retval type='v'/>
</arg>
</method>
但是在我将function_pointer更改为block后,它可以工作。我通过阅读pyobjc单元测试来获得这个块。
<method selector='execute:'>
<arg index='0' type='@?' block='true'>
<arg type='@'/>
<arg type64='Q' type='I'/>
<retval type='v'/>
</arg>
</method>
我不确定是什么原因引起的。 Apple Doc说如果type =“@?”和function_pointer ='true',它被视为块。如果type =“#?”和function_pointer =“true”,它将被解释为function_pointer。但为什么pyobjc无法识别这个?这是pyobjc中的一个错误吗?