Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macos 可以将pyobjc与专用的XPC帮助工具和XPCInterface API一起使用吗?_Macos_Cocoa_Pyobjc_Xpc_Nsxpcconnection - Fatal编程技术网

Macos 可以将pyobjc与专用的XPC帮助工具和XPCInterface API一起使用吗?

Macos 可以将pyobjc与专用的XPC帮助工具和XPCInterface API一起使用吗?,macos,cocoa,pyobjc,xpc,nsxpcconnection,Macos,Cocoa,Pyobjc,Xpc,Nsxpcconnection,我相信这个问题的答案是“不”,但我会把它公布给社区,以防有人比我更成功 我有一个客户端Cocoa应用程序与NSXPCConnection和NSXPCInterface一起使用的特权助手工具。接口本身包括一个通过完成处理程序块提供返回代码的方法 在Objective-C中,客户端代码如下所示: NSXPCConnection * xpcConn = [NSXPCConnection alloc] initWithMachServiceName:kSvcName options:

我相信这个问题的答案是“不”,但我会把它公布给社区,以防有人比我更成功

我有一个客户端Cocoa应用程序与NSXPCConnection和NSXPCInterface一起使用的特权助手工具。接口本身包括一个通过完成处理程序块提供返回代码的方法

在Objective-C中,客户端代码如下所示:

NSXPCConnection * xpcConn = [NSXPCConnection alloc] 
    initWithMachServiceName:kSvcName 
    options:NSXPCConnectionPrivileged];

// MyProtocol defines an instance method runCommand:(NSString*) withReply:^(int result)
NSXPCInterface * mySvcIF = [NSXPCInterface interfaceWithProtocol:@protocol(MyProtocol)];

xpcConn.remoteObjectInterface = mySvcIF;
[xpcConn resume];
if (nil == xpcConn.remoteObjectProxy) {
    NSLog(@"ERROR - remote interface is nil, can't communicate with service");
}

[[xpcConn remoteObjectProxy] runCommand:nsstrCmd withReply:^(int result) {
    NSLog(@"service result is: %d", result);
    if (result != 0) {
        self.svcResult = result;
        self.svcCommandComplete = YES;
    }
}];
objc.registerMetaDataForSelector(b'NSObject', b'runCommand:withReply:', {
'arguments': {
    3: {
       'callable': {
          'retval': {'type': b'@'}, 
          'arguments': {
              0: {'type': b'^v'}, 
              1: {'type': b'i'}, 
          },
       },
    }
  }
})
我还有一个pyobjc/py2app Mac应用程序,需要使用这个助手工具的功能。我已经将该工具内置到pyobjc应用程序包中,并通过SMJobBless进行了签名和授权,但似乎有几个问题使得实际使用该API不受支持:

1) 桥接runCommand:withReply:^的调用似乎不受支持-如果我理解正确,块仅支持NS*框架方法调用,而不支持“自定义”(即用户定义)方法?注意,如果这是唯一的阻塞问题,我可以创建一个没有返回代码的方法版本,但是尝试并没有起到很大的作用,因为

2) 为了以Objective-C的方式使用API,我需要创建一个对runCommand的@selector引用:它实际上没有任何python函数实现——它只需要是一个函数对象,定义将由动态创建的remoteProxy提供的函数的签名。我没有用python定义remoteProxy实现。这似乎不受支持-如果没有python函数,我无法通过objc.selector()获得选择器声明

3) 我不敢肯定,即使我可以开始工作,正式协议的构造也会像预期的那样作为interfaceWithProtocol的参数工作:从python开始,它需要成为一个本地定制@协议,NSXPCInterface可以在其工厂方法中使用它来创建remoteProxy


如果您已经了解了如何在pyobjc中实现这一点,或者根据您对pyobjc的了解明确确认了这一点,那么感谢您提供的任何提示。

前两个子问题很容易回答:使用块调用API是可能的,即使库中不是Apple框架。这确实需要在python代码中做更多的工作,因为Objective-C运行时没有公开足够的信息来完全自动地做正确的事情

对于此特定示例,您可以执行以下操作:

NSXPCConnection * xpcConn = [NSXPCConnection alloc] 
    initWithMachServiceName:kSvcName 
    options:NSXPCConnectionPrivileged];

// MyProtocol defines an instance method runCommand:(NSString*) withReply:^(int result)
NSXPCInterface * mySvcIF = [NSXPCInterface interfaceWithProtocol:@protocol(MyProtocol)];

xpcConn.remoteObjectInterface = mySvcIF;
[xpcConn resume];
if (nil == xpcConn.remoteObjectProxy) {
    NSLog(@"ERROR - remote interface is nil, can't communicate with service");
}

[[xpcConn remoteObjectProxy] runCommand:nsstrCmd withReply:^(int result) {
    NSLog(@"service result is: %d", result);
    if (result != 0) {
        self.svcResult = result;
        self.svcCommandComplete = YES;
    }
}];
objc.registerMetaDataForSelector(b'NSObject', b'runCommand:withReply:', {
'arguments': {
    3: {
       'callable': {
          'retval': {'type': b'@'}, 
          'arguments': {
              0: {'type': b'^v'}, 
              1: {'type': b'i'}, 
          },
       },
    }
  }
})
这将为方法“-[NSObject runCommand:withReply:”注册附加信息。块参数是第3个:计数从0开始,Objective-C方法的前两个参数是“self”和“_sel”(后者未向Python公开)

您通常使用实现该方法的实际类,但我希望这是一个甚至可以动态生成的隐藏类。只要不与其他类冲突,在NSObject上注册元数据应该是安全的

也可以使用Python创建协议:

MyProtocol = objc.formal_protocol('MyProtocol', (), [
    objc.selector(None, b"runCommand:withReply:", signature=b"v@:@@?"),
])
以及使用以下各项创建XPC接口:

mySvcIF = Foundation.NSXPCInterface.interfaceWithProtocol_(MyProtocol)
令人遗憾的是,后一步不起作用,因为NSXPCInterface引发了一个异常:
NSInvalidArgumentException-NSXPCInterface:无法从协议数据获取扩展方法签名(MyProtocol/runCommand:withReply:)。NSXPCInterface需要使用clang。

我已经在PyObjC的追踪器中提交了一个问题:

解决此问题的一个方法是创建一个Python扩展,该扩展包含协议定义以及使用该协议的未使用函数(参见后一部分的示例)。导入扩展后,您可以使用
objc.protocolNamed(“MyProtocol”)
访问协议,该协议将引用由clang创建的完整协议对象,并应与NSXPCInterface一起使用

另外,我很少访问stackoverflow,通过邮寄到pyobjc来吸引我的注意力通常更容易-dev@lists.sourceforge.net(PyObjC邮件列表)