PyObjC и пользовательские блоки - PullRequest
5 голосов
/ 04 мая 2011

Официальная документация гласит, что в коде python можно использовать пользовательские блоки, но вам нужно создавать метаданные.Я не нашел такого примера.

Мой вопрос заключается в том, как создавать, использовать и распространять метаданные для пользовательских блоков.

Пример

@interface SomeClass

- (void)doSomethingWithCompletion: (void (^)(SomeObject *obj, NSError *error))myBlock;

@end


def pythonMethod():
    def completion(obj, error):
        # staff
    foo = SomeClass.new()
    foo.doSomethingWithCompletion_(somehow_pass_completion)

Вопрос в том, как должен выглядеть somehow_pass_completion и как предоставлять метаданные для myBlock.

1 Ответ

6 голосов
/ 04 мая 2011

Упомянутые метаданные - это информация, хранящаяся в формате XML, о типах возврата и аргументов методов Objective-C. Это необходимо для того, чтобы мост PyObjC знал, в какой тип превратить объект Python при передаче его обратно в код Objective-C. Вы можете проверить метаданные, если хотите; он находится в файлах .bridgesupport внутри платформы PyObjC. Например, метаданные AppKit находятся по адресу /System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC/AppKit/PyObjC.bridgesupport. Их можно сгенерировать для любого кода Objective-C, который вы используете gen_bridge_metadata инструмент командной строки от Apple. Для этой утилиты есть справочная страница , и man 5 BridgeSupport также информативен. 1

PyObjC предоставляет функции objc.registerMetaDataForSelector и objc.parseBridgeSupport, которые позволяют добавлять метаданные для ваших методов, используя либо Python dicts (первая функция), либо формат XML, описанный на справочной странице BridgeSupport (последняя) , Примеры использования registerMetaData... доступны в источнике pyobjc по адресу: pyobjc / pyobjc-core / PyObjCTest / test_metadata * (и рядом test_metadata*.py файлы) 2 .

Как пример, это метаданные для -[NSSavePanel beginWithCompletionHandler:], которые принимают блок в качестве аргумента:

<method selector='beginWithCompletionHandler:'>
    <arg index='0' block='true' >
        <retval type='v' />
        <arg type='i' type64='q' />
    </arg>
</method>

Спецификаторы типа arg - это те же Кодировки типов , которые вы получаете от использования @encode в Obj-C. Метаданные для вашего метода должны быть очень похожими.

Итак, поскольку у вас есть прототипы ваших методов в Objective-C, вы должны иметь возможность запустить их через gen_bridge_metadata, чтобы создать файл .bridgesupport, который вы можете включить в ваш проект, а затем использовать objc.parseBridgeSupport, чтобы прочитать этот файл. в. Использование objc.registerMetaDataForSelector также работало для меня в прошлом; проверьте приведенные выше примеры.

Получив метаданные в "системе" PyObjC, вы можете использовать любой старый вызываемый объект в качестве аргумента для метода, который принимает блок:

def pythonMethod():
    def myCompletionHandler(obj, error):
        pass
foo = SomeClass.new()
foo.doSomethingWithCompletion_(myCompletionHandler)

Это всего лишь смесь из нескольких других постов, которые я написал здесь о PyObjC: PyObjC и возвращаемые параметры | Метод индексированного доступа | Проблема с openPanelDidEnd . Возможно, вы тоже захотите взглянуть на них.

Прошло много времени с тех пор, как я с этим справился, так что, возможно, я что-то упустил. Не стесняйтесь спрашивать дополнительную информацию, если вы все еще не можете заставить это работать. Но не сдавайтесь слишком легко - мост - забавный зверь, и иногда вам просто нужно показать, кто в доме хозяин!


1 Еще один документ Apple, который вы должны прочитать: Создание метаданных платформы .
2 Я обнаружил их через ветку списка рассылки pyobjc-dev

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...