ronaldoussoren / pyobjc

The Python <-> Objective-C Bridge with bindings for macOS frameworks
https://pyobjc.readthedocs.io
553 stars 47 forks source link

Documentation Suggestion: how to decorate a 3rd party class/method for pyobjc bridge #229

Open ronaldoussoren opened 6 years ago

ronaldoussoren commented 6 years ago

Original report by Marc Van Olmen (Bitbucket: marc_at_acclivitynyc, ).


Calling one delegate method causes a crash (randomly) with pyobjc bridge.

our app is 32-bit/64-bit

I just read the docs and I couldn't find example how I can do this a 3rd party library, where it has a BOOL parameter and it seems the bridge is trying to pass in an NSNumber object int the 2 examples here below.

Question: So I need to find a way to tell/decorate the 2 methods somehow in python so that pyobjc bridge knows that it is a BOOL parameter?

I look at the following docs. http://pyobjc.readthedocs.io/en/latest/core/typemapping.html https://pythonhosted.org/pyobjc/api/module-objc.html

More detailed info.

this is the Objc delegate method:

#!objective-c

- (NSArray *)feedParametersForUpdater:(SUUpdater *)updater sendingSystemProfile:(BOOL)sendingProfile;

in my python class I wrote this:

#!python

    def feedParametersForUpdater_sendingSystemProfile_(self, updater, showProfileInfo):

calling it from objc like this:

#!objective-c

    if ([delegate respondsToSelector:@selector(feedParametersForUpdater:sendingSystemProfile:)])
        parameters = [parameters arrayByAddingObjectsFromArray:[delegate feedParametersForUpdater:self sendingSystemProfile:sendingSystemProfile]];

The strange thing is that this worked fine for a few times but sometimes it crashes, I have the impression it because the last argument is a BOOL.

also calling the setter method.

#!objective-c

- (void)setAutomaticallyChecksForUpdates:(BOOL)automaticallyChecks;

doesn't work all the time.

ronaldoussoren commented 6 years ago

Original comment by Ronald Oussoren (Bitbucket: ronaldoussoren, GitHub: ronaldoussoren).


UPDATE: I used the wrong decorator in the first version of this message.

I was pretty sure there is documentation about this, but there isn't other than a passing reference in the introduction.

Anyways:

#!python

@objc.signature(b'@@:@Z')
def feedParametersForUpdater_sendingSystemProfile_(self, updater, sending):
       return None

The argument signature is an type encoding for the selector implementation, with encodings for the return value and then all arguments (including two implicit arguments, therefore the second and third character are always "@:").

BTW. If setAutomaticallyChecksForUpdates is implemented in Python it should also be decorated:

#!python

@objc.signature(b'v@:Z')
def setAutomaticallyChecksForUpdates_(self, value):
   pass
ronaldoussoren commented 6 years ago

Original comment by Marc Van Olmen (Bitbucket: marc_at_acclivitynyc, ).


Thanks for the quick response, and pointing me in the right direction. two follow up question.

Q: I'm assuming Z is standing for Bool, is there somewhere a table of possible arguments for this.

Q: setAutomaticallyChecksForUpdates_ is declared in obj-c i assume it would be enough to create category on NSObject like here below?

#!python

class NSObject(objc.Category(NSObject)):
    objc.signature(b'v@:Z')
    def setAutomaticallyChecksForUpdates_(self, value):
        pass
ronaldoussoren commented 6 years ago

Original comment by Ronald Oussoren (Bitbucket: ronaldoussoren, GitHub: ronaldoussoren).


"Z" stands for BOOL, and is a PyObjC invention.

The basic set of type codes is described in an Apple document

The PyObjC additions are not really documented, but you shouldn't need anything beyond "Z" for "BOOL".