PyObjC и возвращение параметров 'out' (т.е. NSError **) - PullRequest
3 голосов
/ 04 декабря 2010

Я реализую протокол ObjC как дополнение к классу PyObjC.

Этот протокол определяет параметр 'out'.

Я не могу найти хорошую документацию о том, как должен вести себя класс Python, реализующий протокол ObjC, определяющий это.

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

Я попробовал это, и все, что я получаю, это исключение при звонке из ObjC (<type 'exceptions.ValueError'>: depythonifying 'char', got 'tuple').

Кажется, что PyObjC строго придерживается протокола ObjC при депитонизации аргументов метода, что приятно, но это не помогает мне пытаться изменить параметр out.

Это протокол ObjC:

#import <Foundation/Foundation.h>

@protocol TestProtocol <NSObject>

- (BOOL)testMethod:(NSError **)error;

@end

Это класс Python, реализующий этот протокол:

from Foundation import *
import objc

NSObject = objc.lookUpClass("NSObject")
TestProtocol = objc.protocolNamed("TestProtocol")

class TestClass(NSObject, TestProtocol):

    def testMethod_(self, error):
        return True, None

ВОПРОС: Как вернуть параметр ObjC out в Python?

Ответы [ 2 ]

3 голосов
/ 11 марта 2011

Этот вопрос старый, поэтому я не знаю, разобрались ли вы к этому моменту, но вы еще не ответили на него, и я некоторое время возился с передачей параметров из Obj-C в Python.Есть несколько вещей, которые вы обязательно должны попробовать / изучить:

Первое и самое простое: когда вы делаете эту заглушку в Objective-C с реализацией на Python, вы должны указать, что (NSError **) это out параметр:

@interface MyObject : NSObject
- (BOOL)testMethod:(out NSError **)error;
@end

Я успешно использовал это для вызова пользовательского метода Obj-C из Python.Я полагаю, что сторона Python не может получить правильные метаданные в противном случае.

Там также добавлен декоратор signature к определению вашего метода Python.Вы можете указать, что один из параметров является параметром out в sig.Этот PyObjC doc содержит подробности.

@objc.signature('@@:io^@')

Другое дело (и вы, возможно, уже поняли это самостоятельно), что если вы не хотите выполнять Цель-C заглушка, вы можете создавать свои собственные метаданные и вставлять файл .bridgesupport в свой проект.Единственная вещь (большая вещь!), В которой я не уверен, это как убедиться, что этот файл действительно прочитан.Сами метаданные действительно легко записывать - Apple предоставляет утилиту командной строки под названием gen_bridge_metadata, и вы можете сделать это вручную (смотрите /System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC/AppKit/PyObjC.bridgesupport).Для этой утилиты есть справочная страница , а man 5 BridgeSupport также информативен.Еще один документ Apple, который вы должны прочитать: Создание метаданных платформы .

ОБНОВЛЕНИЕ для будущих читателей: я нашел функции objc.registerMetaDataForSelector и objc.parseBridgeSupport, обаиз которых вы можете добавить метаданные для ваших методов, используя либо Python dicts (первая функция), либо формат XML, описанный на справочной странице BridgeSupport (последняя).Примеры использования registerMetaData... доступны в источнике pyobjc по адресу: pyobjc / pyobjc-core / PyObjCTest / test_metadata *, который я обнаружил в этом списке рассылки pyobjc-dev thread .

2 голосов
/ 05 декабря 2010

Я попробовал это, и все, что я получаю, это исключение при вызове из ObjC (: депитирование 'char', got 'tuple').

PyObjC обычно передает ошибку обратнокак второй элемент кортежа.

Что-то вроде:

response, error = object.someMethod_error_(foo) # leave off the error
if not response:
    # process error

Увидел ваше обновление ...

Вам либо придется погрузиться в мост метаданных и выяснить, как применить некоторые метаданные во время выполнения к вашей реализации, чтобы заставить его работать.

Или, возможно, намного проще подкласс из скомпилированного класса-заглушки Objective C.

Т.е. попробуйте это:

@interface AbstractFoo : NSObject
@end

@implementation AbstractFoo
- (BOOL) myMethod: (int) arg error: (NSError **) anError;
{
    return YES;
}
@end

Тогда вы сможете подкласс AbstractFoo изсторона Python, и она может"просто работать".

Может быть.

(Извините - давно, так как я был так глубоко в PyObjC)

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