2009-08-12 2 views
5

J'essaie d'utiliser un cadre privé avec PyObjC. J'ai ceci jusqu'à présent:Appelez un sélecteur qui prend un caractère * à partir de PyObjC

from AppKit import * 
from Foundation import * 
import objc 

framework="/System/Library/PrivateFrameworks/DSObjCWrappers.framework" 
objc.loadBundle("DSObjCWrapper", globals(), framework) 

directory = DSoDirectory.alloc() 
directory.initWithHost_user_password_("server", "diradmin", "password") 

eDSStartsWith = 0x2002 
node = directory.findNode_matchType_(u"/LDAPv3", eDSStartsWith) 

Cela fonctionne très bien. Maintenant, je veux appeler une méthode sur mon noeud (de classe DSoNode), avec cette signature objective-c.

  • (BOOL) hasRecordsOfType: (const char *) INTYPE

La façon la plus évidente ne sait pas comment prendre une chaîne et passer à un char *:

node.hasRecordsOfType_("dsRecTypeStandard:ComputerLists") 
--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 

/Users/clinton/<ipython console> in <module>() 

ValueError: depythonifying 'char', got 'str' of 31 

Il semble qu'il soit possible de changer la signature quand python la voit. J'ai essayé quelques variations sur:

objc.registerMetaDataForSelector("DSoNode", "hasRecordsOfType_", dict(arguments={ 2+0: dict(type_modifier='n', type='^C') })) 

, mais - et franchement, je ne sais pas comment la fonction registerMetaDataForSelector fonctionne, et ne l'ai pas trouvé docs - je reçois toujours la même erreur quand j'invoque mon sélecteur sur le noeud. Comment puis-je dire à PyObjC de convertir une chaîne en un caractère *? (Ou est-il une meilleure façon de le faire, car ces chaînes sont des constantes C#defined dans un fichier d'en-tête.)


Mise à jour: J'ai essayé d'utiliser gen_bridge_metadata (comme mentionné in this blog post), et, après avoir consulté l'homme page, essayé comme suit:

sudo mkdir -p /System/Library/PrivateFrameworks/DSObjCWrappers.framework/Resources/BridgeSupport 
sudo gen_bridge_metadata --framework ~/Downloads/DSTools-112.1/build/Deployment/DSObjCWrappers.framework/ --output /System/Library/PrivateFrameworks/DSObjCWrappers.framework/Resources/BridgeSupport/DSObjCWrappers.bridgesupport 

Je reçois toujours la même erreur; il n'y a aucune indication que cela a même été remarqué, sauf que si je tape:

help(modules) 

Je reçois:

/System/Library/PrivateFrameworks/DSObjCWrappers.framework/Versions/A/Resources/<ipython console> in <module>() 

NameError: name 'modules' is not defined 

Je dois aussi mentionner que je trouve une liste des types que je crois serait compris par la fonction registerMetaDataForSelector; objective-C type encodings. Notez que le code XML pour la fonction particulière, je suis dit après:

<method selector='hasRecordsOfType:'> 
<retval type='B'/> 
</method> 

J'aurais quelque chose prévu expliquant le paramètre d'entrée, aussi.

+0

Utilisez c_char_p pour passer le c-string (voir ma réponse) –

Répondre

2

Je crois que vous voulez ce qui suit et devrait alors passer une chaîne non-unicode:

objc.registerMetaDataForSelector("DSoNode", 
           "hasRecordsOfType:", 
      dict(
       arguments = 
       { 
        2: dict(type=objc._C_PTR + objc._C_CHAR_AS_TEXT, 
          c_array_delimited_by_null=True, 
          type_modifier=objc._C_IN) 
       } 
      )) 

Un plus complet exemple NSString suit:

from AppKit import * 
from Foundation import * 
import objc 

def setupMetadata(): 
    objc.registerMetaDataForSelector("NSString", "stringWithCString:", 
     dict(
      arguments = 
      { 
       2: dict(type=objc._C_PTR + objc._C_CHAR_AS_TEXT, 
         c_array_delimited_by_null=True, 
         type_modifier=objc._C_IN) 
      } 
     )) 

def doTest(): 
    s = NSMutableString.stringWithString_(u"foo"); 
    NSLog(u"string[" + s + "]") 

    s2 = NSString.stringWithCString_("bar") 
    NSLog(u"string[" + s2 + "]") 

setupMetadata() 
doTest() 
+0

(Désolé pour la réponse tardive). Cela semble vraiment être sur la bonne voie. Avec les deux exemples, j'obtiens: AttributeError: l'objet 'module' n'a pas d'attribut '_C_CHAR_AS_TEXT' –

+0

Woohoo! Quand j'ai utilisé objc._C_CHR, ça marche! Je suspsect _C_CHAR_AS_TEXT provient d'une version de PyObjC plus récente que celle fournie avec Leopard. –

0

Vous devez appeler hasRecordsOfType comme donc:

from ctypes import * 

typeString = c_char_p('dsRecTypeStandard:ComputerLists') 
node.hasRecordsOfType_(typeString) 
+0

Merci pour la réponse.Quand je l'essaie, j'obtiens: ValueError: depythonifying 'char', obtenu 'c_char_p' –

Questions connexes