1

I have a objc method like this;

@ implementation of Class1

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

}

I want to use this execute method in python, i have build a python objective-c bridge data and it seems to be generated correctly as:

<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>

But when i define a function like this:

def myFunc (dev, index):
    // do something with dev
    print("Hello")

and try to use this as block

class1_obj.execute_(myFunc)

Python throw an errors as:

objc.BadPrototypeError: Objective-C expects 1 arguments, Python argument has 2 arguments for <unbound selector myFunc at 0x105b3a3f0>

I also tried with lambda function, no use.

I also tried to create a callable class as:

>>> 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")

but python throw an error like this:

TypeError: Sorry, cannot create IMP for instances of type myCallable

I am wondering where did I do wrong here?

7
  • I haven't used this in a long time, but as I recall, the <arg function_pointer='true' type='@?' index='0'> should instead be <arg block='true' index='0'>. I'm not at all sure that will solve your problem, though. How did you generate that metadata? Commented Jul 17, 2012 at 23:36
  • i generate the data according to one of your post actually. use apple commandline tool gen_bridge_metadata as instructed by the apple document. Commented Jul 17, 2012 at 23:44
  • It's also funny that if i set the block function takes one argument instead of two, the function will get called. but how to differentiate the two argument... Commented Jul 17, 2012 at 23:45
  • Ah, they must have changed the format. Is the BadPrototypeError happening on the line where you call execute_, or inside, when you call the "Block"? Commented Jul 17, 2012 at 23:52
  • hmm... i am not sure how to tell but here is the output: >>> multiTarget.execute_(myFunc) Traceback (most recent call last): File "<stdin>", line 1, in <module> objc.BadPrototypeError: Objective-C expects 1 arguments, Python argument has 0 arguments for <function myFunc at 0x105af5938> Commented Jul 18, 2012 at 0:08

1 Answer 1

2

Thanks for Josh's suggestion.

Finally got this problem solved. It looks like the meta_data generated by the system using command line gen_bridge_metadata somehow wasn't read correctly. It was generated as:

<method selector='execute:'>
<arg index='0' type='@?' function_pointer='true'>
<arg type='@'/>
<arg type64='Q' type='I'/>
<retval type='v'/>
</arg>
</method>

But after I change the function_pointer to block, it works. I got this by reading through pyobjc unit test for blocks.

<method selector='execute:'>
<arg index='0' type='@?' block='true'>
<arg type='@'/>
<arg type64='Q' type='I'/>
<retval type='v'/>
</arg>
</method>

I am not sure what causes this though. the Apple Doc says if type="@?" and function_pointer='true', it's regarded as block. if type = "#?" and function_pointer="true", it will interpreted as function_pointer. but why pyobjc can't recognize this? is this a bug in pyobjc?

Sign up to request clarification or add additional context in comments.

3 Comments

It seems like PyObjC is doing what the Apple docs say it should (looking for "function_pointer"), if you look at the switch inside PyObjC_processXML() in pyobjc-core/Modules/objc/parsexml.m, but I still haven't examined this in detail. Are you maybe using an older version of PyObjC?
hmm. maybe. I am using the one that comes with Lion 10.7.4 on Mac OS. I am not sure if this is an old copy of it though.
That should be sufficiently up-to-date. Oh, well. I'll get back to you if I figure anything else out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.