2009-08-12 2 views
5

Я пытаюсь использовать частную фреймворк с PyObjC. У меня это до сих пор:Вызовите селектор, который принимает char * от 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) 

Это прекрасно работает. Теперь я хочу вызвать метод на моем узле (класса DSoNode) с этой целью-c-сигнатурой.

  • (BOOL) hasRecordsOfType: (Const символ *) inType

Самый очевидный способ не знает, как взять строку и передать его в символ *:

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

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

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

Похоже, что можно изменить подпись, как видит ее python. Я пробовал некоторые вариации:

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

но - и честно говоря, я не знаю, как работает функция registerMetaDataForSelector, и не нашел документы на него - я все еще получаю ту же ошибку, когда я вызываю мой селектор на узле. Как сообщить PyObjC преобразовать строку в char *? (Или есть лучший способ сделать это, так как эти строки C константы с помощью #define в заголовочном файле.)


Обновление: Я попытался с помощью gen_bridge_metadata (как уже упоминалось in this blog post), и после консультаций с человеком страницы, попробовал его следующим образом:

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 

Я все еще получаю ту же ошибку; нет никаких признаков того, что это было даже замечено, за исключением того, что если я типа:

help(modules) 

я получаю:

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

NameError: name 'modules' is not defined 

Я должен также упомянуть, что я нашел список типов, которые я считаю, было бы понятно, функцией registerMetaDataForSelector; objective-C type encodings. Обратите внимание, что XML для конкретной функции я после говорит:

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

я бы ожидал чего-то объясняющую входным параметром тоже.

+0

Использовать c_char_p для передачи c-string (см. мой ответ) –

ответ

2

Я считаю, что вы хотите следующее, а затем должен пройти не-юникод строку:

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

Более полный пример NSString следующим образом:

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

(Извините за запоздалый ответ). Это действительно похоже, что это на правильном пути. В обоих примерах я получаю: AttributeError: объект 'module' не имеет атрибута '_C_CHAR_AS_TEXT' –

+0

Woohoo! Когда я использовал objc._C_CHR, он работает! Я подозреваю, что _C_CHAR_AS_TEXT исходит из версии PyObjC, более новой, чем версия, которая поставляется с Leopard. –

0

Вы должны вызвать hasRecordsOfType как так:

from ctypes import * 

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

Спасибо за ответ.Когда я пытаюсь, я получаю: ValueError: depythonifying 'char', получил 'c_char_p' –

Смежные вопросы