Skip to main content

Compile and import Zig functions at runtime without building a package

Project description

import-zig

pip install import-zig

This module provides a way to import Zig code directly into Python using a single function call to import_zig. Here is an example:

from import_zig import import_zig

mod = import_zig(source_code = """
    pub fn Q_rsqrt(number: f32) f32 {
        const threehalfs: f32 = 1.5;
        const x2 = number * 0.5;
        var y = number;
        var i: i32 = @bitCast(y);
        i = 0x5f3759df - (i >> 1);
        y = @bitCast(i);
        y = y * (threehalfs - (x2 * y * y));

        return y;
    }
""")

print(f"1 / sqrt(1.234) = {mod.Q_rsqrt(1.234)}")

The main goal of this module is to make it easy to prototype Zig extensions for Python without having to engage with the Python build system. When building larger Zig extensions it is likely preferable to write your own build process with setuptools or to use a ziggy-pydust template, which provides a comptime abstraction over many aspects of the Python C API. Zig and Zig extensions are still very new though, so things will likely change. Technically you could also use this module as part of a packaging step by calling the compile_to function to build the binary and moving it into the packages build folder.

One approach that I expect to stay the same is the comptime wrapping for conversion between Zig and Python types as well as exception handling. This is conveniently packed into the file py_utils.zig and could be copy pasted into a new setuptools based project and maybe adjusted.

See the docs of the import_zig function for more details or check out the examples directory.

File structure

The file structure that will be generated to compile the Zig code looks as follows.

project_folder
├── root_source_file.zig
├── build.zig
├── build.zig.zon
└── zig_ext
    ├── c.h
    ├── generated.zig
    ├── .gitignore
    ├── py_utils.zig
    └── zig_ext.zig

The project_folder and more specifically root_source_file.zig is where your code lives. When you pass a source code string or file path, it will be written / linked directly to root_source_file.zig file. When you pass a directory path alongside the file name of your root_source_file, the entire directory will be linked / copied, allowing use of multiple zig files and extended by the two build.zig* files as well as the zig_ext directory.

The above file structure (minus the root_source_file.zig) can be generated with:

import_zig.prepare("/path/to/project_folder", "module_name")

This enables ZLS support for the Python C API when importing c or py from your root_source_file.

Type mapping

The conversion is defined in py_utils.zig and applied based on the parameter / return types of the exported function. Errors are also forwarded. The solution to passing variable length data back to Python is a bit of a hack: When an exported function specifies std.mem.Allocator as a parameter type, then an arena allocator - which gets deallocated after the function call - will be passed into the function. The allocator can then be used to allocate and return new slices for example.

For nested types, the conversion is applied recursively.

Conversion from Python Zig datatype Conversion to Python
int integer (any size / sign) int
float float (any size) float
- void None
evaluated like bool() bool bool
sequence array list
sequence non u8 const slice list
str u8 const slice str
dict or sequence struct tuple if struct is a tuple or named tuple
comparison with None optional null -> None

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

import_zig-0.15.1.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

import_zig-0.15.1-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

File details

Details for the file import_zig-0.15.1.tar.gz.

File metadata

  • Download URL: import_zig-0.15.1.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for import_zig-0.15.1.tar.gz
Algorithm Hash digest
SHA256 5f4c80ed2d2ffbd6b098eab7a90acc7793acb508af991d591d5aafd6c995570c
MD5 c97156028b8d4b306fcf7a5a67c9130d
BLAKE2b-256 51253321dd4cf000dfd79a9bdee98435d726378b6a5b14cfce2465f3ba9bd59e

See more details on using hashes here.

File details

Details for the file import_zig-0.15.1-py3-none-any.whl.

File metadata

  • Download URL: import_zig-0.15.1-py3-none-any.whl
  • Upload date:
  • Size: 13.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for import_zig-0.15.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6fb36f745c5eb07609cb594e400bc542827dab562b9e6f25621c80c0970a8784
MD5 0a96425f964bb3c11269c0af7aac1e1f
BLAKE2b-256 f5da2ec5a44474d55f87b1ddefa277ade00e767cb8795072d3b753cd969c6680

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page