2009-08-12 16 views
5

Estoy tratando de utilizar un marco privado con PyObjC. Tengo esto hasta ahora:Llamar a un selector que toma un char * 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) 

Eso funciona bien. Ahora, quiero llamar a un método en mi nodo (de la clase DSoNode), con esta firma objetivo-c.

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

La manera más obvia no sabe cómo tomar una cadena y pasarlo a 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 

Parece que es posible cambiar la firma como lo ve pitton. Probé algunas variaciones en:

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

pero - y francamente no sé cómo funciona la función registerMetaDataForSelector, y no he encontrado documentos en él - sigo teniendo el mismo error cuando invoco mi selector en el nodo. ¿Cómo le digo a PyObjC que convierta una cadena en un char *? (¿O hay una mejor manera de hacerlo, ya que estas cadenas son constantes C#defined en un fichero de cabecera.)


Actualización: He intentado utilizar gen_bridge_metadata (como se ha mencionado in this blog post), y, previa consulta al hombre página, lo intenté de la siguiente manera:

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 

Sigo recibiendo el mismo error; no hay ninguna indicación de que esto era aún la atención, excepto que si escribo:

help(modules) 

me sale:

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

NameError: name 'modules' is not defined 

También debo mencionar que he encontrado una lista de tipos que creo que se entendería por la función registerMetaDataForSelector; objective-C type encodings. Tenga en cuenta que el XML para la función particular que estoy después dice:

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

me hubiera esperado algo que explica el parámetro de entrada, también.

+0

Use c_char_p para pasar el c-string (ver mi respuesta) –

Respuesta

2

creo que desea que el siguiente y luego debe pasar una cadena no 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 ejemplo más completo NSString siguiente manera:

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

(Disculpa la respuesta tardía). Esto realmente parece estar en el camino correcto. Con ambos ejemplos, obtengo: AttributeError: el objeto 'module' no tiene atributo '_C_CHAR_AS_TEXT' –

+0

Woohoo! Cuando usé objc._C_CHR, ¡funciona! Sospecho _C_CHAR_AS_TEXT proviene de una versión de PyObjC más nueva que la que se envía con Leopard. –

0

usted tiene que llamar hasRecordsOfType como entonces:

from ctypes import * 

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

Gracias por la respuesta.Cuando lo intento, obtengo: ValueError: depythonifying 'char', got 'c_char_p' –

Cuestiones relacionadas