1

我有一个像这样的 objc 方法;

@ implementation of Class1

- (void)execute:(void (^)(Class2* target, NSUInteger idx))block
{
... 

}

我想在 python 中使用这个执行方法,我已经构建了一个 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

我想知道我在这里做错了什么?

4

1 回答 1

2

感谢乔希的建议。

终于解决了这个问题。看起来系统使用命令行 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 说 if type="@?" 而function_pointer='true',则视为块。如果类型=“#?” 和 function_pointer="true",它将被解释为 function_pointer。但是为什么 pyobjc 不能识别呢?这是 pyobjc 中的错误吗?

于 2012-07-19T04:09:09.853 回答