Вызовите селектор, который берет символ * из PyObjC

Я пытаюсь использовать частный фреймворк с 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) с этой сигнатурой target-c.

  • (BOOL) hasRecordsOfType: (const char *) 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 преобразовать строку в символ *? (Или есть лучший способ сделать это, так как эти строки являются константами C#defined в заголовочном файле.)


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

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; кодировки типа C Обратите внимание, что XML для конкретной функции, которую я ищу, говорит:

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

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

2 ответа

Решение

Я считаю, что вы хотите следующее, а затем должны передать не-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)
                }
            ))

Более полный пример 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()

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

from ctypes import *

typeString = c_char_p('dsRecTypeStandard:ComputerLists')
node.hasRecordsOfType_(typeString)
Другие вопросы по тегам