2009-08-12 5 views
5

Ich versuche, ein privates Framework mit PyObjC zu verwenden. Ich habe das so weit:Aufruf eines Selektors, der ein Char * von PyObjC akzeptiert

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) 

Das funktioniert gut. Nun möchte ich eine Methode auf meinem Knoten (der Klasse DSoNode) mit dieser Ziel-c-Signatur aufrufen.

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

Der offensichtlichste Weg nicht weiß, wie eine Zeichenfolge zu nehmen und es in eine * char passieren:

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

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

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

Es sieht so aus, als wäre es möglich, die Signatur zu ändern, wenn Python sie sieht. Ich habe versucht, einige Varianten zu:

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

aber - und ehrlich gesagt weiß ich nicht, wie die registerMetaDataForSelector Funktion funktioniert, und haben nicht docs darauf gefunden - ich immer noch den gleichen Fehler, wenn ich meine Wähler aufrufen auf dem Knoten. Wie sage ich PyObjC, um eine Zeichenkette in ein char * zu konvertieren? (Oder gibt es einen besseren Weg, es zu tun, wie diese Strings sind C Konstanten in einer Header-Datei #defined.)


Update: Ich habe versucht, gen_bridge_metadata mit (als in this blog post erwähnt), und nach dem Mann Beratung Seite, versuchte es wie folgt:

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 

Ich bekomme immer noch den gleichen Fehler; es gibt keine Anzeichen dafür, dass dies auch auffiel, war, mit der Ausnahme, dass, wenn ich schreibe:

help(modules) 

ich:

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

NameError: name 'modules' is not defined 

ich auch erwähnen sollte, dass ich eine Liste von Arten gefunden, die ich glaube, würde verstehen, durch die Funktion registerMetaDataForSelector; objective-C type encodings. Beachten Sie, dass die XML für die jeweilige Funktion Ich bin nach, sagt:

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

Ich würde etwas erklären den Eingabeparameter erwartet habe, auch.

+0

Mit c_char_p übergeben der C-String (siehe meine Antwort) –

Antwort

2

Ich glaube, Sie das folgende wollen und dann eine Nicht-Unicode-String übergeben sollte:

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) 
       } 
      )) 

Eine vollständigere NSString Beispiel folgt:

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

(Entschuldigung für die verspätete Antwort). Das sieht wirklich so aus, als wäre es auf dem richtigen Weg. Mit beiden Beispielen bekomme ich: AttributeError: 'Modul' Objekt hat kein Attribut '_C_CHAR_AS_TEXT' –

+0

Woohoo! Wenn ich objc._C_CHR verwendet habe, funktioniert es! Ich suspsect _C_CHAR_AS_TEXT kommt von einer Version von PyObjC neuer als die, die mit Leopard geliefert wird. –

0

Sie haben hasRecordsOfType zu nennen wie so:

from ctypes import * 

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

Danke für die Antwort.Wenn ich es versuche, bekomme ich: ValueError: dephythonifying 'char', bekam 'c_char_p' –

Verwandte Themen