2009-08-12 13 views
5

Próbuję użyć prywatnej struktury z PyObjC. Mam to do tej pory:Wywołanie selektora, który pobiera znak * z 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) 

To działa dobrze. Teraz chcę wywołać metodę na moim węźle (klasy DSoNode), z tym podpisem c-cel.

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

Najbardziej oczywistym sposobem nie umie podjąć ciąg i przekazać go do char *:

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

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

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

Wygląda na to, że istnieje możliwość zmiany podpisu tak, jak widzi go python. Próbowałem kilka wersji:

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

ale - i szczerze mówiąc nie wiem, w jaki sposób działa funkcja registerMetaDataForSelector, i jeszcze nie znaleziono dokumenty na nim - ja wciąż dostać ten sam błąd, gdy wzywam mojego wyboru na węźle. Jak mogę powiedzieć PyObjC, aby przekonwertować ciąg znaków na znak *? (Lub czy istnieje lepszy sposób to zrobić, ponieważ te ciągi są stałe C#defined w pliku nagłówka.)


Aktualizacja: Próbowałem za pomocą gen_bridge_metadata (jak wspomniano in this blog post), i po konsultacji z człowieka strona, wypróbowany w następujący sposób:

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 

Nadal dostaję ten sam błąd; nic nie wskazuje, że jest to nawet nie zauważył, poza tym, że jeśli typ:

help(modules) 

uzyskać:

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

NameError: name 'modules' is not defined 

Należy również wspomnieć, że znalazłem listę typów, które wierzę, że należy rozumieć przez funkcję registerMetaDataForSelector; objective-C type encodings. Zauważ, że XML dla określonej funkcji Jestem po mówi:

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

bym oczekiwany coś wyjaśniający parametru wejściowego, zbyt.

+0

Użyj c_char_p, aby przejść c-string (patrz moja odpowiedź) –

Odpowiedz

2

wierzę chcesz następujących czynności, a następnie należy przekazać ciąg 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) 
       } 
      )) 

Pełniejszy przykład NSString następuje:

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

(Przepraszam za spóźnioną odpowiedź). Wygląda na to, że jest na dobrej drodze. W przypadku obu przykładów otrzymuję: AttributeError: obiekt "module" nie ma atrybutu "_C_CHAR_AS_TEXT" –

+0

Woohoo! Kiedy użyłem obiektu objc._C_CHR, działa! Podejrzewam, że _C_CHAR_AS_TEXT pochodzi z wersji PyObjC nowszej niż wersja dostarczana z Leopardem. –

0

Trzeba zadzwonić hasRecordsOfType jak więc:

from ctypes import * 

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

Dzięki za odpowiedź.Kiedy próbuję, otrzymuję: ValueError: depythonifying "char", dostałem "c_char_p" –

Powiązane problemy