PyObjC 并返回“out”;参数(即 NSError **)

发布于 2024-10-06 08:17:54 字数 1067 浏览 6 评论 0 原文

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

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

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

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

我已经尝试过了,但从 ObjC 调用时得到的只是一个异常(: depythonifying 'char', got 'tuple')。

看来 PyObjC 在 depythonifying 方法参数中严格遵守 ObjC 协议,这很好,但它不能帮助我尝试修改输出参数。

这是 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 输出参数?

I'm implementing an ObjC protocol as a mix-in for a PyObjC class.

This protocol defines an 'out' parameter.

I am unable to find any good documentation on how a Python class which implements an ObjC protocol defining this is to behave.

I've found this mailing list thread but the suggestion in there does not work. They say to return a Python list with the method's return value as the first item and the out parameter as the second.

I've tried this and all I get is an exception when calling from ObjC (<type 'exceptions.ValueError'>: depythonifying 'char', got 'tuple').

It seems PyObjC strictly adheres to the ObjC protocol in depythonifying method arguments, which is nice but it doesn't help me trying to modify an out parameter.

This is the ObjC protocol:

#import <Foundation/Foundation.h>

@protocol TestProtocol <NSObject>

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

@end

This is the Python class implementing this protocol:

from Foundation import *
import objc

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

class TestClass(NSObject, TestProtocol):

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

QUESTION: How do I return an ObjC out parameter in Python?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

温柔女人霸气范 2024-10-13 08:17:54

这个问题很老了,所以我不知道你现在是否已经解决了,但你还没有回答它,不久前我正在忙着从 Obj-C 到 Python 获取参数。有几件事你绝对应该尝试/研究:

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

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

我已成功使用它从 Python 调用自定义 Obj-C 方法。我相信 Python 端否则无法获得正确的元数据。

还向您的 Python 方法定义添加了一个 signature 装饰器。您可以指定其中一个参数是 sig 中的输出参数。此 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 字典(前一个函数)或 BridgeSupport 手册页中描述的 XML 格式(后者)。使用 registerMetaData... 的示例可在 pyobjc 源代码中找到:pyobjc/pyobjc-core/PyObjCTest/test_metadata*,我通过这个 pyobjc-dev 邮件列表线程

This question's old, so I don't know if you've sorted it out by now, but you haven't answered it, and I was fussing with getting out parameters from Obj-C to Python a short while ago. There are a few things that you should definitely try/look into:

First and simplest is: when you make that stub in Objective-C with the implementation in Python, you've got to specify that the (NSError **) is an out parameter:

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

I've used this successfully to call a custom Obj-C method from Python. I believe the Python side doesn't get the right metadata otherwise.

There's also adding a signature decorator to your Python method definition. You can specify that one of the parameters is an out parameter in the sig. This PyObjC doc gives details.

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

The other thing is (and you may have figured this out on your own by now) that if you don't want to do the Objective-C stub, you may be able to generate your own metadata and stick a .bridgesupport file into your project. The only thing (the big thing!) that I'm not sure of is how to make sure that this file actually gets read. The metadata itself is really easy to write -- Apple supplies a command-line utility called gen_bridge_metadata, and you could do it by hand (look at /System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC/AppKit/PyObjC.bridgesupport). Theres a man page for that utility, and man 5 BridgeSupport is also informative. Another Apple doc you should read is: Generating Framework Metadata.

UPDATE for future readers: I've found the functions objc.registerMetaDataForSelector and objc.parseBridgeSupport, both of which allow you to add metadata for your methods, using either Python dicts (the former function) or the XML format described in the BridgeSupport man page (the latter). Examples of using registerMetaData... are available in the pyobjc source at: pyobjc/pyobjc-core/PyObjCTest/test_metadata*, which I discovered via this pyobjc-dev mailing list thread.

傲娇萝莉攻 2024-10-13 08:17:54

我已经尝试过了,我得到的只是一个
从 ObjC 调用时出现异常
(:
对“char”进行反Python化,得到“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 了)

I've tried this and all I get is an
exception when calling from ObjC
(:
depythonifying 'char', got 'tuple').

PyObjC generally passes the error back as the second element of a tuple.

Something like:

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

Saw your update...

You are either going to have to dive into the metadata bridge and figure out how to apply some metadata at runtime to your implementation to make it work.

Or, possibly much easier, is to subclass from a compiled Objective-C stub class.

I.e. try this:

@interface AbstractFoo : NSObject
@end

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

Then, you should be able to subclass AbstractFoo from the Python side and it might "just work".

Maybe.

(Sorry -- been a while since I've been this deep in PyObjC)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文