PyObjC并返回'out'参数(即NSError **)

时间:2010-12-04 12:06:36

标签: cocoa pyobjc

我正在实施一个ObjC协议作为PyObjC类的混合。

此协议定义了'out'参数。

我无法找到任何关于如何实现定义此ObjC协议的Python类的行为的良好文档。

我发现了这个mailing list thread,但那里的建议不起作用。他们说要返回一个Python列表,方法的返回值为第一项,out参数为第二项。

我试过这个,从ObjC(<type 'exceptions.ValueError'>: depythonifying 'char', got 'tuple')打电话时我得到的只是一个例外。

似乎PyObjC在depythonifying方法参数中严格遵守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

问题:如何在Python中返回ObjC out参数?

2 个答案:

答案 0 :(得分:3)

这个问题已经过时了,所以我不知道你现在是否已经把它整理出来了,但是你还没有回答它,我很想在不久前将参数从Obj-C输出到Python。您应该尝试/研究一些事项:

首先也是最简单的一点是:当您在Objective-C中使用Python实现该存根时,您必须指定(NSError **) out 参数:

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

我已成功使用它从Python调用自定义Obj-C方法。我相信Python方面没有得到正确的元数据。

还在Python方法定义中添加了signature装饰器。您可以指定其中一个参数是sig中的out参数。这个PyObjC doc提供了详细信息。

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

另一件事是(你现在可能已经想到了这一点)如果你不想做Objective-C存根,你可以生成自己的元数据并坚持.bridgesupport将文件存入您的项目。我不确定的唯一(大事!)是如何确保这个文件实际上被读取。元数据本身非常容易编写 - Apple提供了一个名为gen_bridge_metadata的命令行实用程序,您可以手动完成(查看/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python /PyObjC/AppKit/PyObjC.bridgesupport)。该实用程序的man pageman 5 BridgeSupportGenerating Framework Metadata也提供了丰富的信息。您应阅读的另一个Apple文档是:pyobjc/pyobjc-core/PyObjCTest/test_metadata*

未来读者的

更新:我找到了函数objc.registerMetaDataForSelectorobjc.parseBridgeSupport,这两个函数都允许您使用Python dicts为您的方法添加元数据(前一个函数)或BridgeSupport手册页(后者)中描述的XML格式。使用registerMetaData...的示例可在pyobjc源代码中找到:thread,我通过此pyobjc-dev邮件列表{{3}}发现。

答案 1 :(得分:2)

  

我已经尝试过了,而且我得到的只是一个   从ObjC调用时的异常   (:   depythonifying'char',得到'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

然后,您应该可以从Python端继承AbstractFoo可能“只是工作”。

可能。

(对不起 - 我已经在PyObjC深入了一段时间)