跳转到主要内容

setuptools扩展,用于使用Zig构建cpython扩展。

项目描述

https://sourceforge.net/p/setuptools-zig/code/ci/default/tree/_doc/_static/license.svg?format=raw https://sourceforge.net/p/setuptools-zig/code/ci/default/tree/_doc/_static/pypi.svg?format=raw https://sourceforge.net/p/oitnb/code/ci/default/tree/_doc/_static/oitnb.svg?format=raw

这是一个setuptools扩展,用于使用Zig编译器构建用Zig和/或C编写的cpython扩展。

此扩展期望在您的PATH中找到zig命令。如果它不在那里,或者如果您需要选择特定的版本,您可以设置环境变量PY_ZIG为可执行文件的完整路径。例如:

PY_VER=/usr/local/bin/zig

此模块版本的已更新到Zig 0.10.0,但应与其他版本兼容(只要您适应您的Zig代码)。它已在Ubuntu 22.4(二进制zig安装)和macOS 13.0.1(brew安装)上与Python 3.7 - 3.11进行了测试。

PyPI上有setuptools-zig软件包,但不需要安装,因为它是一个设置需求。一旦您的setup.py文件有适当的条目,构建sdistbdist_wheel将自动下载软件包(缓存在.eggs目录中)。

setup.py

您的setup.py文件应如下所示

from setuptools import Extension
from setuptools import setup

setup(
    name=NAME,
    version='MAJ.MIN.PATCH',
    python_requires='>=3.7.15%',
    build_zig=True,
    ext_modules=[Extension(NAME, [XX1, XX2])],
    setup_requires=['setuptools-zig'],
)

其中NAME由您的软件包名称替换。将MAJ、MIN和PATCH替换为您的软件包版本,XX1、XX2为您的源文件(您可以只有一个,也可以有多个)。

将此适用于您的项目

python setup.py bdist_wheel

将在您的dist目录中生成一个.whl文件。此wheel文件可以在虚拟环境中安装,并且可以导入和使用包中定义的函数。默认情况下,编译和/或链接命令执行将显示,只有在发生错误时才会显示输出。可以通过指定-v-vv来增加详细程度,在bdist_wheel之后。

将Zig用作C编译器

创建您的 setup.py

from setuptools import Extension
from setuptools import setup

setup(
    name='c_sum',
    version='1.0.0',
    python_requires='>=3.7.15',
    build_zig=True,
    ext_modules=[Extension('c_sum', ['sum.c', ])],
    setup_requires=['setuptools-zig'],

sum.c

/* based on https://docs.pythonlang.cn/3.9/extending/extending.html */

#define PY_SSIZE_T_CLEAN
#include <Python.h>

PyObject* sum(PyObject* self, PyObject* args) {
    long a, b;

    if (!PyArg_ParseTuple(args, "ll", &a, &b))
            return NULL;
    return PyLong_FromLong(a+b);
}


static struct PyMethodDef methods[] = {
    {"sum", (PyCFunction)sum, METH_VARARGS},
    {NULL, NULL}
};

static struct PyModuleDef zigmodule = {
    PyModuleDef_HEAD_INIT,
    "sum",
    NULL,
    -1,
    methods
};

PyMODINIT_FUNC PyInit_c_sum(void) {
    return PyModule_Create(&zigmodule);

使用 pip 安装生成的 wheel 文件并使用

python -c "from c_sum import sum; print(sum(20, 22))"

使用 Zig 与 .zig 和 .c

Zig 编译器可以轻松混合搭配(见 macOS 部分),这里我们使用 C 代码提供接口,并在 Zig 中执行计算总和的重劳工作。

setup.py:

from setuptools import Extension
from setuptools import setup

setup(
    name='c_zig_sum',
    version='1.0.0',
    python_requires='>=3.7.15',
    build_zig=True,
    ext_modules=[Extension('c_zig_sum', ['c_int.c', 'sum.zig', ])],
    setup_requires=['setuptools-zig'],
)

c_int.c:

/* based on https://docs.pythonlang.cn/3.9/extending/extending.html */

#define PY_SSIZE_T_CLEAN
#include <Python.h>

PyObject* sum(PyObject* , PyObject*);

/*
PyObject* sum(PyObject* self, PyObject* args) {
    long a, b;

    if (!PyArg_ParseTuple(args, "ll", &a, &b))
        return NULL;
    return PyLong_FromLong(a+b);
}
*/


static struct PyMethodDef methods[] = {
    {"sum", (PyCFunction)sum, METH_VARARGS},
    {NULL, NULL}
};

static struct PyModuleDef zigmodule = {
    PyModuleDef_HEAD_INIT,
    "c_zig_sum",
    NULL,
    -1,
    methods
};

PyMODINIT_FUNC PyInit_c_zig_sum(void) {
    return PyModule_Create(&zigmodule);
}

sum.zig:

const c = @cImport({
    @cDefine("PY_SSIZE_T_CLEAN", "1");
    @cInclude("Python.h");
});

pub export fn sum(self: [*]c.PyObject, args: [*]c.PyObject) [*c]c.PyObject {
    var a: c_long = undefined;
    var b: c_long = undefined;
    _ = self;
    if (!(c._PyArg_ParseTuple_SizeT(args, "ll", &a, &b) != 0)) return null;
    return c.PyLong_FromLong((a + b));

Zig 代码仅

原始转换的代码难以阅读。在 Python 3.7/3.8/3.9/3.10/3.11 之间,从 C 转换的特定程序 Zig 代码没有差异(但当然在头文件中有差异)。这是一个尝试整理事物的初步尝试。仅需要在注释行下的部分需要根据您的项目进行适配。

setup.py:

from setuptools import Extension
from setuptools import setup

setup(
    name='zig_sum',
    version='1.0.1',
    python_requires='>=3.7.15',
    build_zig=True,
    ext_modules=[Extension('zig_sum', ['sum.zig' ])],
    setup_requires=['setuptools-zig'],
)

sum.zig:

const c = @cImport({
    @cDefine("PY_SSIZE_T_CLEAN", "1");
    @cInclude("Python.h");
});

const PyObject = c.PyObject;

const PyModuleDef_Base = extern struct {
    ob_base: PyObject,
    // m_init: ?fn () callconv(.C) [*c]PyObject = null,
    m_init: ?*const fn () callconv(.C) [*c]PyObject = null,
    m_index: c.Py_ssize_t = 0,
    m_copy: [*c]PyObject = null,
};

const PyModuleDef_HEAD_INIT = PyModuleDef_Base {
    .ob_base = PyObject {
        .ob_refcnt = 1,
        .ob_type = null,
    }
};

const PyMethodDef = extern struct {
    ml_name: [*c]const u8 = null,
    ml_meth: c.PyCFunction = null,
    ml_flags: c_int = 0,
    ml_doc: [*c]const u8 = null,
};

const PyModuleDef = extern struct {
    // m_base: c.PyModuleDef_Base,
    m_base: PyModuleDef_Base = PyModuleDef_HEAD_INIT,
    m_name: [*c]const u8,
    m_doc: [*c]const u8 = null,
    m_size: c.Py_ssize_t = -1,
    m_methods: [*]PyMethodDef,
    m_slots: [*c]c.struct_PyModuleDef_Slot = null,
    m_traverse: c.traverseproc = null,
    m_clear: c.inquiry = null,
    m_free: c.freefunc = null,
};

/////////////////////////////////////////////////

pub export fn sum(self: [*]PyObject, args: [*]PyObject) [*c]PyObject {
    var a: c_long = undefined;
    var b: c_long = undefined;
    _ = self;
    if (!(c._PyArg_ParseTuple_SizeT(args, "ll", &a, &b) != 0)) return null;
    return c.PyLong_FromLong((a + b));
}

pub var methods = [_:PyMethodDef{}]PyMethodDef{
    PyMethodDef{
        .ml_name = "sum",
        .ml_meth = @ptrCast(c.PyCFunction, @alignCast(@import("std").meta.alignment(c.PyCFunction), &sum)),
        .ml_flags = @as(c_int, 1),
        .ml_doc = null,
    },
};

pub var zigmodule = PyModuleDef{
    .m_name = "zig_sum",
    .m_methods = &methods,
};

pub export fn PyInit_zig_sum() [*c]c.PyObject {
    return c.PyModule_Create(@ptrCast([*c]c.struct_PyModuleDef, &zigmodule));
}

macOS

在 macOS 上运行 zig build-lib 将生成一个无法由 Python 加载的 .dylib 文件。相反,setuptools-zig 将对单个源文件运行 zig build-obj(因为将 .c.zig 文件组合会导致错误),然后使用 clang -bundle.o 文件组合起来,生成可加载的 .so 文件。

清理

在 Zig 0.10.0 中运行 zig build-obj sum.zig 会生成 sum.osum.o.o 两个文件。此扩展尝试清理这些额外的文件。

项目详情


下载文件

下载您平台的文件。如果您不确定该选择哪个,请了解更多关于 安装包 的信息。

源分布

setuptools_zig-0.2.0.tar.gz (6.5 kB 查看散列)

上传时间 源代码

构建分布

setuptools_zig-0.2.0-py3-none-any.whl (6.9 kB 查看散列)

上传时间 Python 3

由以下机构支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面