我正在实施一个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参数?
答案 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 page为man 5 BridgeSupport
,Generating Framework Metadata也提供了丰富的信息。您应阅读的另一个Apple文档是:pyobjc/pyobjc-core/PyObjCTest/test_metadata*。
更新:我找到了函数objc.registerMetaDataForSelector
和objc.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深入了一段时间)