Первые два подвопроса просты для ответа: API можно вызывать с блоками, даже в библиотеках, которые не являются фреймворками Apple. Это требует дополнительной работы в коде Python, потому что среда выполнения Objective C не предоставляет достаточно информации, чтобы полностью автоматически делать правильные вещи.
Для этого конкретного примера вы можете сделать что-то вроде этого:
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: Unable to get extended method signature from Protocol data (MyProtocol / runCommand:withReply:). Use of clang is required for NSXPCInterface.
.
Я подал проблему для этого в трекере PyObjC: https://bitbucket.org/ronaldoussoren/pyobjc/issues/256/enable-using-xpcinterface-with-protocols.
Обходной путь для этой проблемы - создать расширение Python, которое содержит определение протокола, а также неиспользуемую функцию, которая использует протокол (см., Например, https://bitbucket.org/ronaldoussoren/pyobjc/src/default/pyobjc-framework-Cocoa/Modules/_AppKit_protocols.m для последней части). После импорта расширения вы можете использовать objc.protocolNamed("MyProtocol")
для доступа к протоколу, который будет ссылаться на полный объект протокола, созданный clang, и должен работать с NSXPCInterface.
P.S. Я редко обращаюсь к stackoverflow, часто легче привлечь мое внимание, отправив письмо по адресу pyobjc-dev@lists.sourceforge.net (список рассылки PyObjC).