-
-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added support for sending blocks to objc #54
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! Overall everything looks good to me, but I have a couple of small questions/comments, see below.
Sorry that I haven't been able to review this sooner, I wasn't at my computer for the last few days.
rubicon/objc/objc.py
Outdated
@@ -1696,3 +1726,62 @@ def __call__(self, *args): | |||
class ObjCBlockInstance(ObjCInstance): | |||
def __call__(self, *args): | |||
return self.block(*args) | |||
|
|||
|
|||
_NSConcreteGlobalBlock = ObjCClass("__NSGlobalBlock__") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The __NSGlobalBlock__
class isn't actually documented anywhere. _NSConcreteGlobalBlock
is documented, but not required to be an Objective-C class (you're only supposed to use its address).
So the officially supported way to use this would be:
_NSConcreteGlobalBlock = (c_void_p * 32).in_dll(c, "_NSConcreteGlobalBlock")
# ... when setting the isa ...
self.literal.isa = addressof(_NSConcreteGlobalBlock)
(_NSConcreteGlobalBlock
is declared as a void *[32]
in Block.h
.)
rubicon/objc/objc.py
Outdated
self.descriptor.reserved = 0 | ||
self.descriptor.size = sizeof(BlockLiteral) | ||
|
||
encoding_for_ctype(restype) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This discards the return value from the encoding_for_ctype
call - is this intentional? If so, it would be good to add a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like leftover debugging code from me.
rubicon/objc/types.py
Outdated
@@ -235,7 +238,8 @@ def ctype_for_encoding(encoding): | |||
|
|||
def encoding_for_ctype(ctype): | |||
"""Return the Objective-C type encoding for the given ctypes type.""" | |||
|
|||
if isinstance(ctype, POINTER_TYPE): | |||
return b'^' + encoding_for_ctype(ctype._type_) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be in the except KeyError
block below, so that pointer types that are in _encoding_for_ctype_map
are looked up there. For example POINTER(c_char)
should encode as *
, not as ^c
.
This adds support for sending blocks to objc. It supports both "automagical python callable to objc block style" (which in non-trivial cases can segfault due to python GC) as well as "explicit create a block object style" through the
rubicon.objc.Block
.Magical style (functions need to be fully annotated):
Explicit style: