Macos 可以将pyobjc与专用的XPC帮助工具和XPCInterface API一起使用吗?
我相信这个问题的答案是“不”,但我会把它公布给社区,以防有人比我更成功 我有一个客户端Cocoa应用程序与NSXPCConnection和NSXPCInterface一起使用的特权助手工具。接口本身包括一个通过完成处理程序块提供返回代码的方法 在Objective-C中,客户端代码如下所示: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:
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邮件列表)