辻斬り Generic C++ Bindings Generator
Project description
tsujikiri — 辻斬り
Cut through C++ bindings
tsujikiri parses C++ headers via libclang, filters by namespace and pattern, transforms symbols — rename, remap types, inject code — then renders ready-to-compile bindings through a Jinja2 template. Precise control, zero boilerplate.
Built-in support for LuaBridge3 (Lua bindings), LuaLS (Lua Language Server annotations), pybind11 (Python bindings), and Python type stubs (.pyi). Custom formats are first-class.
How It Works
C++ Header (.hpp)
│
▼ libclang
Intermediate Representation (IR)
│
├─▶ FilterEngine suppress classes / methods / fields by pattern
│
├─▶ Transform Pipeline rename, inject, remap types
│
▼ Jinja2 templates
Target Binding Code
Each phase is independently configurable per input file and per output format.
Documentation
Full documentation is available at tsujikiri.readthedocs.io.
Installation
Using pip:
pip install tsujikiri
Using uv:
uv pip install tsujikiri
Requirements: Python ≥ 3.12
Clang Version
By default tsujikiri installs libclang-ng>=19, which resolves to the latest available version. To pin a specific Clang release use an extra:
# pip
pip install "tsujikiri[clang19]"
pip install "tsujikiri[clang20]"
pip install "tsujikiri[clang21]"
pip install "tsujikiri[clang22]"
# uv
uv pip install "tsujikiri[clang21]"
Only one clangXX extra may be active at a time — they are mutually exclusive.
Quick Start
1. Write an input config
# myproject.input.yml
source:
path: myproject.hpp
parse_args: ["-std=c++17"]
include_paths: ["/usr/local/include"]
filters:
namespaces: ["myproject"]
classes:
whitelist: ["Vec3", "Matrix4", "Camera"]
constructors:
include: true
generation:
includes: ["<myproject.hpp>"]
2. Generate bindings
# Print to stdout
tsujikiri -i myproject.input.yml --target luabridge3 -
# Write to file
tsujikiri -i myproject.input.yml --target luabridge3 bindings.cpp
# Generate multiple outputs in one pass
tsujikiri -i myproject.input.yml \
--target luabridge3 bindings.cpp \
--target pybind11 py_bindings.cpp \
--target pyi mymodule.pyi
# Dry-run: parse and filter, print summary
tsujikiri -i myproject.input.yml --target luabridge3 - --dry-run
# List available formats
tsujikiri --list-formats
3. Example output (LuaBridge3)
Given a header with a Vec3 class, tsujikiri emits:
#include <myproject.hpp>
#include <LuaBridge/LuaBridge.h>
void register_myproject(lua_State* L)
{
luabridge::getGlobalNamespace(L)
.beginClass<myproject::Vec3>("Vec3")
.addConstructor<void(*)(float, float, float)>()
.addFunction("length", &myproject::Vec3::length)
.addFunction("dot", &myproject::Vec3::dot)
.addProperty("x", &myproject::Vec3::x)
.addProperty("y", &myproject::Vec3::y)
.addProperty("z", &myproject::Vec3::z)
.endClass();
}
Built-in Formats
luabridge3
Generates C++ registration code for LuaBridge3.
tsujikiri -i project.input.yml --target luabridge3 bindings/lua_bindings.cpp
Handles: classes, constructors, instance/static methods, overloaded methods, properties, enums, free functions, inheritance.
luals
Generates Lua Language Server annotation stubs.
tsujikiri -i project.input.yml --target luals types/myproject.lua
Emits ---@class, ---@field, ---@param, ---@return annotations with C++→Lua type mappings.
pybind11
Generates C++ registration code for pybind11.
tsujikiri -i project.input.yml --target pybind11 src/py_bindings.cpp
Handles: classes with multiple inheritance, constructors, instance/static methods, overloaded methods (via py::overload_cast), read-write/read-only properties, enums (via py::enum_), free functions, doc strings.
pyi
Generates Python type stub files (.pyi) for use alongside pybind11 bindings.
tsujikiri -i project.input.yml --target pyi mymodule.pyi
Emits Python-typed stubs with @overload, @staticmethod, class inheritance, enum stubs as class Foo(int), and C++→Python type mappings.
Custom Formats
Create a myformat.output.yml alongside your templates:
format_name: "myformat"
format_version: "1.0"
description: "My custom binding format"
type_mappings:
"std::string": "String"
"int32_t": "int"
unsupported_types:
- "CFStringRef"
template:
{%- block prologue -%}
# DO NOT EDIT - Auto-generated Python stubs for {{ module_name }} by tsujikiri
from __future__ import annotations
from typing import overload
{{ code_injections | code_at("beginning") }}
{%- endblock %}
# ... finish the template
Point tsujikiri at your format directory:
tsujikiri -i project.input.yml --target myformat out/bindings.cpp -f ./my_formats/
CLI Reference
usage: tsujikiri [-h] [--input FILE] [--target FORMAT FILE] [--formats-dir DIR] [--list-formats] [--dry-run] [--manifest-file FILE]
[--check-compat] [--embed-version] [--trace-transforms] [--dump-ir [FILE]] [--validate-config] [--verbose] [--api-version VERSION]
辻斬り — Generic C++ Binding Generator
options:
-h, --help show this help message and exit
--input FILE, -i FILE
Input config YAML (e.g. myproject.input.yml)
--target FORMAT FILE, -t FORMAT FILE
Output target: FORMAT is a built-in name (luabridge3) or path to .output.yml; FILE is the output path ('-' for stdout). Repeatable.
--formats-dir DIR, -f DIR
Additional directory to search for .output.yml format files (repeatable)
--list-formats Print available built-in output formats and exit
--dry-run Parse and filter but do not generate output; print a summary instead
--manifest-file FILE, -m FILE
Write API manifest JSON to FILE; if FILE already exists, compare with new manifest
--check-compat Exit 1 if --manifest-file exists and breaking API changes are detected
--embed-version Embed the API version hash in the generated code (template must support it)
--trace-transforms Print which transform stages ran and on what entities to stderr
--dump-ir [FILE] Dump the post-transform IR as JSON to FILE (default: stdout when flag is given without FILE)
--validate-config Validate the input config YAML (regex patterns, transform stage names) and exit
--verbose, -v Enable verbose output during parsing (currently only applies to Clang diagnostics)
--api-version VERSION
Target API version (semver). Entities with api_since > VERSION or api_until <= VERSION are excluded.
Development
# Install task runner and sync dependencies
pip install just uv
just sync
# Run tests
just test
# Run tests with coverage
just coverage
# Build wheel
just build
The test suite covers parsing, filtering, transforms, generation, CLI integration, and end-to-end compilation with LuaBridge3.
Coverage
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tsujikiri-0.13.0.tar.gz.
File metadata
- Download URL: tsujikiri-0.13.0.tar.gz
- Upload date:
- Size: 65.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c6c55035017d50a1e45d7257aef258686f575cab35dae27ae9d4a82396dc224
|
|
| MD5 |
42b3cf143785c69122be2bab6ef17de6
|
|
| BLAKE2b-256 |
c747ac25c365a299b1a1caf7ddad7aa260be2f5a00f616c4ea0985216711afd9
|
Provenance
The following attestation bundles were made for tsujikiri-0.13.0.tar.gz:
Publisher:
release.yml on kunitoki/tsujikiri
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tsujikiri-0.13.0.tar.gz -
Subject digest:
7c6c55035017d50a1e45d7257aef258686f575cab35dae27ae9d4a82396dc224 - Sigstore transparency entry: 1367959099
- Sigstore integration time:
-
Permalink:
kunitoki/tsujikiri@8c1016f819a162d3a4998560659b3d8ceb9d75ee -
Branch / Tag:
refs/tags/v0.13.0 - Owner: https://github.com/kunitoki
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8c1016f819a162d3a4998560659b3d8ceb9d75ee -
Trigger Event:
push
-
Statement type:
File details
Details for the file tsujikiri-0.13.0-py3-none-any.whl.
File metadata
- Download URL: tsujikiri-0.13.0-py3-none-any.whl
- Upload date:
- Size: 76.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b38e63f47eb3e93fdf69b9d4e8575dc3ab8893fe93d04f363bf17694c8c0522c
|
|
| MD5 |
4dc3d604847e17b1e034af9ac6acaa1c
|
|
| BLAKE2b-256 |
f3bcb31c4fe34f857bd3baa70fdc92072155dc7442c1824e4e8c6a3b644a6305
|
Provenance
The following attestation bundles were made for tsujikiri-0.13.0-py3-none-any.whl:
Publisher:
release.yml on kunitoki/tsujikiri
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tsujikiri-0.13.0-py3-none-any.whl -
Subject digest:
b38e63f47eb3e93fdf69b9d4e8575dc3ab8893fe93d04f363bf17694c8c0522c - Sigstore transparency entry: 1367959199
- Sigstore integration time:
-
Permalink:
kunitoki/tsujikiri@8c1016f819a162d3a4998560659b3d8ceb9d75ee -
Branch / Tag:
refs/tags/v0.13.0 - Owner: https://github.com/kunitoki
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8c1016f819a162d3a4998560659b3d8ceb9d75ee -
Trigger Event:
push
-
Statement type: