调用从PyObjC获取char*的选择器

Cli*_*ore 5 pyobjc pointers objective-c 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)
Run Code Online (Sandbox Code Playgroud)

这很好.现在,我想在我的节点(类DSoNode)上调用一个方法,使用此objective-c签名.

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

最明显的方法是不知道如何获取字符串并将其传递给char*:

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

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

ValueError: depythonifying 'char', got 'str' of 31
Run Code Online (Sandbox Code Playgroud)

看起来可以在python看到它时更改签名.我尝试了一些变化:

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

但是 - 坦率地说我不知道​​registerMetaDataForSelector函数是如何工作的,并且还没有找到文档 - 当我在节点上调用我的选择器时,我仍然会得到相同的错误.如何告诉PyObjC将字符串转换为char*?(或者有更好的方法,因为这些字符串是头文件中的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
Run Code Online (Sandbox Code Playgroud)

我仍然得到同样的错误; 没有迹象表明这甚至被注意到,除非我输入:

help(modules)
Run Code Online (Sandbox Code Playgroud)

我明白了:

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

NameError: name 'modules' is not defined
Run Code Online (Sandbox Code Playgroud)

我还要提一下,我发现了一个类型列表,我相信registerMetaDataForSelector函数可以理解这些类型; Objective-C类型编码.请注意,我所关注的特定函数的XML说:

<method selector='hasRecordsOfType:'>
<retval type='B'/>
</method>
Run Code Online (Sandbox Code Playgroud)

我也期望解释输入参数的东西.

nal*_*all 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)
                }
            ))
Run Code Online (Sandbox Code Playgroud)

更完整的 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()
Run Code Online (Sandbox Code Playgroud)