-
-
Notifications
You must be signed in to change notification settings - Fork 54
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
Support mapping Objective-C classes to custom ObjCInstance subclasses #81
Support mapping Objective-C classes to custom ObjCInstance subclasses #81
Conversation
This is somewhat similar to the existing system for converting type encodings to ctypes types.
Their description methods return nil, which previously caused a type error when it was returned from __str__. ObjC[Meta]Class now have a custom __str__, and ObjCInstance.__str__ now detects description methods returning nil and raises a more useful exception.
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 looks really good. I'll approve it on the grounds that it looks solid as is, assuming the tests pass (still waiting on those... Travis really is getting flaky...)
I've got one note on the general API, but I'm not hugely fussed about it if you disagree.
@@ -1208,7 +1259,7 @@ def __new__(cls, object_ptr, _name=None, _bases=None, _ns=None): | |||
if is_block: | |||
cls = ObjCBlockInstance | |||
else: | |||
cls = cls._select_mixin(object_ptr) | |||
cls = type_for_objcclass(libobjc.object_getClass(object_ptr)) |
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.
Is there any reason that the is_block
check couldn't be merged into type_for_objcclass
?
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.
Yes, unfortunately. is_block
is assigned at the very top of ObjCInstance.__new__
, and is used to remember whether the object_ptr
that was originally passed to the constructor was of type objc_block
. That information would be lost otherwise, because object_ptr
is cast to objc_id
in the next line.
Even if that wasn't the case, type_for_objcclass
takes a class pointer, and the block check happens on the instance pointer. And the reason why we have to rely on the type of the instance pointer at all is because there's no good way to tell at runtime whether an object is a block or not.
Yeah, Mac Travis is as reliable as usual. Four of the five builds ran fine, the remaining one failed to |
Nevermind, the build ran just now. That was much quicker than I expected. |
Yes, it's another type mapping registry. This is a replacement for
ObjCClass._select_mixin
, which is not extensible and not very efficient as it grows (as I noted in #70). The new system uses a mapping to keep track of which Python type corresponds to which Objective-C class, which is more efficient and allows easy addition of extra types. This is now used internally forObjCProtocol
andObjC[Mutable](List|Dict)Instance
, but theoretically it can also be used externally.ObjCClass
,ObjCMetaClass
andObjCBlockInstace
are still special-cased inObjCInstance.__new__
. They cannot be registered using the new system, because there is no single Objective-C base class for all classes, metaclasses or blocks.