Python与Objective-C的代码生成方法桥接器
项目描述
ObjP的目标是在Python和Objective-C之间创建双向桥接。与使用运行时方法动态调用的PyObjC不同,ObjP生成静态代码。它可以为Python代码生成Objective-C接口,或者为Objective-C代码生成Python模块。
库非常简单,正是为了这个目的。与PyObjC不同,ObjP不可能完全封装整个Cocoa框架,支持的东西太多。ObjP旨在允许您桥接自己的代码。
请注意,ObjP适用于Python 3.2及以上版本。
我认为学习如何使用ObjP的最佳方式是查看示例。'demos'子文件夹中有许多示例。这些示例使用waf构建(它已包含在内,无需安装)。例如,如果您想构建simple演示,请执行以下操作:
$ cd demos/simple $ ./waf configure build $ cd build $ ./HelloWorld
该程序从Objective-C调用一个简单的Python脚本,该Python脚本本身调用一个Objective-C类。
用法
有两种类型的桥接:封装Python类的Objective-C类(o2p)和封装Objective-C类的Python类(p2o)。
要生成o2p封装器,您需要一个目标类。此外,为了封装此类的方法,您需要正确注释其参数和返回值(您可以在演示中找到如何操作的优秀示例)。以下是一个正确注释的类的示例
class Foo: def hello_(self, name: str) -> str: return "Hello {}".format(name)
要封装此类,您将使用此方式中的objp.o2p.generate_objc_code()
import foo import objp.o2p objp.o2p.generate_objc_code(foo.Foo, 'destfolder')
这将生成“Foo.h|m”以及“ObjP.h|m”,存放在“destfolder”中。这些源文件直接使用Python API,没有其他依赖项。
要生成p2o封装器,您需要一个包含接口或协议的Objective-C头文件或描述该接口的Python类
@interface Foo: NSObject {} - (NSString *)hello:(NSString *)name; @end
要从这些生成Python封装器,您可以这样做
import objp.p2o objp.p2o.generate_python_proxy_code(['Foo.h'], 'destfolder/Foo.m')
这将生成一个Python扩展模块的代码,用于包装Foo。扩展模块的名称由目标源文件的名称决定。您可以在同一单元中包装多个类。
objp.p2o.generate_python_proxy_code(['Foo.h', 'Bar.h'], 'destfolder/mywrappers.m')
方法名称转换
ObjP遵循PyObjC的方法名称转换约定。由于Python方法名称中不允许使用“:”字符,因此它们被下划线替换。因此,一个方法- (BOOL)foo:(NSInteger)arg1 bar:(NSString *)arg2;被转换为def foo_bar_(self, arg1: int, arg2: str) -> bool:,反之亦然。
请注意,如果您的方法的参数数量与您的方法名称中的下划线数量不对应,objp将发出警告并忽略该方法。
参数类型
ObjP只支持少数几种参数类型,目标是为了保持项目简单。
int/NSInteger
float/CGFloat
str/NSString*
bool/BOOL
list/NSArray*
dict/NSDictionary*
nspoint/NSPoint
nssize/NSSize
nsrect/NSRect
ObjP还支持object,它根据参数类型动态转换参数,并返回一个NSObject子类(这意味着int、float和bool将转换为NSNumber而不是转换为NSInteger、CGFloat和BOOL)。这种转换类型用于转换list和dict的内容(直接在NSArray中包含BOOL是不可能的)。
另一种特殊的参数类型是pyref(您必须在代码中从objp.util导入它),它只是简单地传递PyObject*实例而不进行转换。
结构参数允许您将元组转换为原生objc结构,反之亦然。Python没有“原生”的结构用于点、大小和矩形,因此我们将其转换为/从元组((x, y)、(w, h)和(x, y, w, h))进行转换。与pyref一样,ns*签名参数必须从objp.util导入。
实用工具
objp.util包含pyref和ns*参数类型,但它还包含两个有用的方法装饰器:dontwrap和objcname。带有dontwrap装饰的方法将被代码生成器忽略,而带有@objcname('some:selector:')装饰的方法将使用此名称生成objc代码而不是自动生成的名称。
常量转换
当在两种不同的语言中编写代码时,我们有时需要在两者之间共享常量。为了避免手动维护Objective-C中Python常量的对应物,objp提供了一个小型实用工具,objp.const.generate_objc_code(module, dest)。它将module命名空间中的所有元素转换为在dest中的Objective-C常量单元。
int、float和str类型将被转换为#define <name> <str(value)>(str值周围带有@"")。您还可以在Python常量模块中拥有枚举类。如果一个类有整数成员,则认为它是一个枚举。例如
class Foo: Bar = 1 Baz = 2
将被转换为
typedef enum { FooBar=1, FooBaz=2 } Foo;
因为这个函数会在无法转换的任何值上卡住,建议您只将它用于专门为该目的编写的模块上,例如从您的真实常量单元导入的 cocoa_const.py。由于 Objective-C 中的常量通常有前缀,您也可以在单元中添加它们。它可能看起来像这样
from real_const import FOO as XZFOO, BAR as XZBAR, MyEnum as XZMyEnum
更改
版本 1.3.2 – 2016/01/09
修复了 generate_python_proxy_code_from_clsspec() 中的错误。
修复了 ObjP_list_o2p() 中的编译警告。
版本 1.3.1 – 2014/10/04
修复了在转换包含不支持类型的 NSDictionary 时崩溃的问题。
版本 1.3.0 – 2012/09/27
增加了将 Python 常量模块转换为 Objective-C 代码的支持。
版本 1.2.1 – 2012/05/28
将代理的目标成员名称从 py 改为 _py,以避免当参数被命名为 y 时与局部变量发生名称冲突。
版本 1.2.0 – 2012/02/01
增加了对 NSPoint、NSSize 和 NSRect 结构的支持。
在 ObjP_str_o2p() 中,当字符串是 nil 时,返回 Py_None 而不是崩溃。
版本 1.1.0 – 2012/01/23
允许在 p2o 集合转换中包含空项(使用 [NSNull null])。
增加了对浮点数的支持。
p2o 转换返回 NSObject 子类的现在可以将 None 转换为 nil。
版本 1.0.0 – 2012/01/16
增加了对协议的支持。
增加了对 __init__ 方法包装的支持。
增加了 bool 和 pyref 参数类型。
增加了支持创建包装现有 objc 实例的 p2o 实例。
增加了异常检查。
增加了 GIL 锁定。
增加了继承支持。
增加了在同一 p2o 模块中包装多个类。
版本 0.1.1 – 2012/01/08
修复了损坏的设置。
修复了损坏的 o2p。
版本 0.1.0 – 2012/01/05
首次发布
项目详情
下载文件
下载适合您平台的文件。如果您不确定要选择哪个,请了解更多关于 安装包 的信息。
源代码发行版
构建发行版
objp-1.3.2.tar.gz 的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | ff1d4a8db6ae326759a390b71659b8338e5bcf9302a54b401ae0891e73e32474 |
|
MD5 | aa11d944c3eb950ce1bac4b2fd4170c1 |
|
BLAKE2b-256 | 291325cd0d3f8daf5919a8257db7958774b23cf234ad4c0e89672cee37b118d9 |
objp-1.3.2-py3-none-any.whl的哈希值
算法 | 散列摘要 | |
---|---|---|
SHA256 | 62dd7ea430f18790d2c823832ff76737a9175b8089b64e040a5b6816842af0e2 |
|
MD5 | 8705f99f306abf264b4457440ae9e1ce |
|
BLAKE2b-256 | 3cb6f85265d83da1c32dfc6fb2540e3fb470b1dbe596b2ef62aabf533192412c |