4

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

该协议定义了一个“out”参数。

我找不到任何关于实现定义它的 ObjC 协议的 Python 类如何表现的好的文档。

我找到了这个邮件列表线程,但其中的建议不起作用。他们说要返回一个 Python 列表,其中方法的返回值作为第一项,out 参数作为第二项。

<type 'exceptions.ValueError'>: depythonifying 'char', got 'tuple'我已经尝试过了,我得到的只是从 ObjC ( )调用时出现的异常。

似乎 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 输出参数?

4

2 回答 2

5

这个问题很老了,不知道你现在有没有整理出来,但是你还没有回答,前段时间我还在为从 Obj-C 到 Python 中取出参数而烦恼。您绝对应该尝试/研究一些事情:

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

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

我已经成功地使用它从 Python 调用自定义 Obj-C 方法。我相信 Python 方面不会获得正确的元数据。

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

@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 5 BridgeSupport信息丰富。您应该阅读的另一个 Apple 文档是:生成框架元数据

更新给未来的读者:我找到了函数objc.registerMetaDataForSelectorobjc.parseBridgeSupport,它们都允许您使用 Python dicts(前一个函数)或 BridgeSupport 手册页中描述的 XML 格式(后者)为您的方法添加元数据。registerMetaData...pyobjc 源代码中提供了使用示例: pyobjc/pyobjc-core/PyObjCTest/test_metadata*,这是我通过这个 pyobjc-dev 邮件列表线程发现的。

于 2011-03-11T09:40:03.997 回答
4

我已经尝试过了,我得到的只是从 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

然后,您应该能够AbstractFoo从 Python 端进行子类化,并且它可能“正常工作”。

也许。

(抱歉——自从我深入 PyObjC 以来已经有一段时间了)

于 2010-12-04T21:19:10.483 回答