2010-12-04 3 views
3

J'implémente un protocole ObjC en tant que mix-in pour une classe PyObjC.PyObjC et renvoyer les paramètres 'out' (c'est-à-dire NSError **)

Ce protocole définit un paramètre 'out'.

Je suis incapable de trouver une bonne documentation sur la façon dont une classe Python qui implémente un protocole ObjC définissant ceci doit se comporter.

J'ai trouvé ceci mailing list thread mais la suggestion dedans ne fonctionne pas. Ils disent de retourner une liste Python avec la valeur de retour de la méthode en tant que premier élément et le paramètre out en tant que deuxième.

J'ai essayé ceci et tout ce que je reçois est une exception lors de l'appel de ObjC (<type 'exceptions.ValueError'>: depythonifying 'char', got 'tuple').

Il semble que PyObjC adhère strictement au protocole ObjC dans les arguments de méthode depythonifying, ce qui est bien, mais cela ne m'aide pas à essayer de modifier un paramètre out.

C'est le protocole ObjC:

#import <Foundation/Foundation.h> 

@protocol TestProtocol <NSObject> 

- (BOOL)testMethod:(NSError **)error; 

@end 

Ceci est la classe Python mise en œuvre de ce protocole:

from Foundation import * 
import objc 

NSObject = objc.lookUpClass("NSObject") 
TestProtocol = objc.protocolNamed("TestProtocol") 

class TestClass(NSObject, TestProtocol): 

    def testMethod_(self, error): 
     return True, None 

QUESTION: Comment puis-je retourner un ObjC paramètre out en Python?

Répondre

3

vieux, de cette question, donc je ne sais pas si vous avez par résoudre notre problème maintenant, mais vous n'avez pas Il m'a répondu, et j'étais en train de sortir des paramètres d'Obj-C à Python il y a peu de temps.Il y a quelques choses que vous devez absolument essayer/regarder dans:

première et la plus simple est la suivante: lorsque vous faites ce talon en Objective-C avec la mise en œuvre en Python, vous devez spécifier que le (NSError **) est un out paramètre:

@interface MyObject : NSObject 
- (BOOL)testMethod:(out NSError **)error; 
@end 

Je l'ai utilisé ce paramètre pour appeler avec succès une méthode personnalisée Obj-C de Python. Je crois que le côté Python n'obtient pas les bonnes métadonnées autrement.

Vous ajoutez également un décorateur signature à votre définition de méthode Python. Vous pouvez spécifier que l'un des paramètres est un paramètre out dans le sig. Ce PyObjC doc donne des détails.

@objc.signature('@@:io^@') 

L'autre chose est (et vous pouvez avoir compris cela vous-même maintenant) que si vous ne voulez pas faire le talon Objective-C, vous pourriez être en mesure de générer vos propres métadonnées et coller un fichier .bridgesupport dans votre projet. La seule chose (la grande chose!) Dont je ne suis pas sûr est de savoir comment s'assurer que ce fichier est effectivement lu. Les métadonnées elles-mêmes sont vraiment faciles à écrire - Apple fournit un utilitaire de ligne de commande appelé gen_bridge_metadata, et vous pouvez le faire à la main (voir /System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python /PyObjC/AppKit/PyObjC.bridgesupport). Theres un man page pour cet utilitaire, et man 5 BridgeSupport est également informatif. Un autre document Apple que vous devriez lire est: Generating Framework Metadata.

Mise à jour pour les futurs lecteurs: J'ai trouvé les fonctions objc.registerMetaDataForSelector et objc.parseBridgeSupport, les deux qui vous permettent d'ajouter des métadonnées pour vos méthodes, en utilisant soit dicts Python (l'ancienne fonction) ou le format XML décrit dans le BridgeSupport page de man (ce dernier). Des exemples d'utilisation de registerMetaData... sont disponibles dans la source pyobjc au: pyobjc/pyobjc-core/PyObjCTest/test_metadata*, que j'ai découvert via cette liste de diffusion pyobjc-dev thread.

2

J'ai essayé cela et tout ce que je reçois est une exception lors de l'appel de ObjC (: depythonifying 'char', a obtenu 'tuple').

PyObjC transmet généralement l'erreur en tant que deuxième élément d'un tuple.

Quelque chose comme:

response, error = object.someMethod_error_(foo) # leave off the error 
if not response: 
    # process error 

vu votre mise à jour ...

Vous êtes soit allez devoir plonger dans le pont de métadonnées et comprendre comment appliquer des métadonnées à l'exécution de votre implémentation pour le faire fonctionner.

Ou, peut-être beaucoup plus facile, est de sous-classe à partir d'une classe tronquée Objective-C compilé.

I.e. essayez ceci:

@interface AbstractFoo : NSObject 
@end 

@implementation AbstractFoo 
- (BOOL) myMethod: (int) arg error: (NSError **) anError; 
{ 
    return YES; 
} 
@end 

Ensuite, vous devriez être en mesure de sous-classe AbstractFoo du côté Python et peut-être « juste ».

Peut-être.

(Désolé - été un certain temps depuis que je suis profondément dans ce PyObjC)

+0

"PyObjC transmet généralement l'erreur en tant que deuxième élément d'un tuple." Oui, c'est ce que fait ma méthode Python (testMethod_). Mais PyObjC n'adhère pas à cette règle lors de la dépythonisation dans la zone ObjC, et renvoie ensuite une exception. La confusion de toutes les réponses sur Internet que j'ai vues, semble provenir de la distinction entre l'appel de ObjC de Python contre l'appel de Python de ObjC. Je suis intéressé par ce dernier. On ne se comporte pas comme les autres. – firstresponder

+0

Merci bbum. J'ai essayé de créer une classe Stub ObjC et d'en hériter en Python, comme vous l'avez suggéré mais j'ai la même exception ("depythonifying 'char', got 'tuple'"). Connaissez-vous des endroits où je peux trouver de la documentation sur la façon de commencer à jouer avec les technologies de pont? – firstresponder

+0

ugh - bummer. Le meilleur pari est de lire la source. C'est l'une des raisons pour lesquelles je détourne les gens de l'utilisation des ponts pour faire du développement de Cocoa à moins que vous ayez vraiment * vraiment * besoin de mélanger une bibliothèque de la langue désirée .... Désolé je ne pourrais pas être plus utile. – bbum