llpyg: LLGo 快速集成 Python 生态的桥梁
前言
LLGo[1] 是一款基于 LLVM 的 Go 编译器,通过 LLVM 为 Go 语言整合了 C 和 Python 语言生态,让开发者可以更工程化地在 Go 中使用海量的 Python 生态库,比如直接使用 numpy、torch 等库。
要实现在 Go 中使用 Python 库,需要有对应的 LLGo Bindings 代码,才能通过 LLGo 的二进制接口 (ABI) 调用 Python 库。生成一个 Python 库对应的接口代码,需要对库中定义的函数、类、变量等符号进行映射。但完全依赖人工的映射过程不仅效率低下,且极易引入难以察觉的错误。特别是当面对包含成百上千个 API 的大型 Python 库时,这种手动映射工作几乎成为不可能完成的任务。
正是基于解决这一核心痛点的迫切需求,llpyg[2] 自动化生成工具应运而生,旨在将这个耗时且易错的手动过程转变为高效、准确的自动化过程。
llpyg 开源地址:https://github.com/goplus/llpyg
1、核心功能
符号提取
通过 Python 运行时反射机制,动态获取 Python 模块中的符号信息:
基于 CPython API,提取模块中的变量、函数、类等各类符号信息。
支持从文档注释中提取 C 扩展函数的签名信息。
签名解析
根据函数/方法的签名字符串,解析出所包含的参数信息:
支持解析可选参数、默认参数、位置参数、关键字参数等。
通过签名中的
/和*等符号,对参数进行分组。
代码生成
在代码生成方面,llpyg:
支持函数、类、变量等 Python 对象的代码生成。
支持类继承、类方法、类属性等 Python 语言特性。
自动生成符合 Go 语言风格的函数、结构体和方法。
2、工作流程
llpyg 项目结构如下:

整体流程如下:
执行
pyenv,设置 Python 路径,对环境进行检查。执行
pymodule,获取 Python 库的多级模块名,生成配置文件。逐模块执行
pygen,生成 LLGo Bindings 代码。
pygen 具体流程如下:
执行
pydump,获取 Python 库的符号信息,包括函数、类等信息。执行
pysig,解析 Python 函数和方法签名。根据符号和签名信息使用工具
gogen生成 Go 代码。
3、符号映射
在 llpyg 中,我们使用通用类型 py.Object 来表示 Python 对象。每一个 Python 对象都可以被映射为 py.Object 类型。

对于 Python 模块中定义的全局函数,我们使用包级别的函数来进行映射,传入参数类型统一为 *py.Object。

为了提供对于 Python 类的支持,我们使用结构体来表示 Python 类,通过结构体嵌入实现类似继承的效果:

针对每一个 Python 类,我们提供了一个包级别的构造函数 New[ClassName] 用于创建实例:

对于实例方法,我们将其转为结构体方法:

对于类实例中存在的 property 属性,我们将其拆分为了 get 和 set 方法:

4、运行示例
接下来,我们以 numpy 库为例,展示 llpyg 的使用方法。
程序输入
用户可以通过以下命令一键生成 numpy 库的 LLGo Bindings 代码:

同时支持在命令中添加以下参数:
-o: 指定 LLGo Bindings 代码的输出目录-mod: 为生成的 LLGo Bindings 初始化为 Go Module-d: 期望转换的 Python 库的模块的最大深度
用户还可以通过编写配置文件的方式来生成 LLGo Bindings 代码:

配置文件示例如下:

name: 生成的 Go Package 名称libName: 要转换的 Python 库名称modules: 要转换的 Python 库的模块
输出结果
llpyg 会将生成的代码组织为一个 Go Module,结构如下:

Go 文件中存放 Python 模块对应的 LLGo Bindings 代码。例如,对于 numpy.add 函数:

llpyg 生成的 LLGo Binding 为:

使用示例
用户可以像使用 Go 函数一样使用 Python 函数:

输出:

5、未来发展
lpyg 正致力于扩展其功能,包括:
支持更多 Python 语言特性,如装饰器、生成器等。
实现更精确的类型推断和转换。
逐步探索 Python 生态中复杂库的生成能力。
通过持续优化,llpyg 将为 LLGo 开发者提供更高效、更可靠的 Python 库绑定生成工具,进一步推动 Go 和 Python 生态的融合。
引用链接
[1] LLGo: https://github.com/goplus/llgo
[2] llpyg: https://github.com/goplus/llpyg