Skip to main content

辻斬り Generic C++ Bindings Generator

Project description

Backdrop

Tests Type Check Coverage Documentation PyPI version Python License: MIT

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


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

tsujikiri [OPTIONS]

Options:
  -i, --input FILE            Input config YAML (required)
  -t, --target FORMAT FILE    Output target: FORMAT is a built-in name or path to
                              .output.yml; FILE is the output path ('-' for stdout).
                              Repeatable for multiple simultaneous outputs.
  -c, --classname CLASS       Generate bindings for a single class only
  -f, --formats-dir DIR       Extra directory to search for .output.yml files (repeatable)
      --list-formats          Print available formats and exit
      --dry-run               Parse and filter only; print IR summary without generating
  -m, --manifest-file FILE    Write API manifest JSON to FILE; compare if FILE exists
      --check-compat          Exit 1 if manifest shows breaking API changes
      --embed-version         Embed the API version hash in the generated code
      --trace-transforms      Print transform stages and their targets to stderr
      --dump-ir [FILE]        Dump the post-transform IR as JSON (default: stdout)
      --validate-config       Validate input config (regex patterns, stage names) and exit
  -h, --help                  Show this message and exit

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

Coverage tree


License

MIT — see LICENSE.

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

tsujikiri-0.9.0.tar.gz (65.1 kB view details)

Uploaded Source

Built Distribution

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

tsujikiri-0.9.0-py3-none-any.whl (74.9 kB view details)

Uploaded Python 3

File details

Details for the file tsujikiri-0.9.0.tar.gz.

File metadata

  • Download URL: tsujikiri-0.9.0.tar.gz
  • Upload date:
  • Size: 65.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tsujikiri-0.9.0.tar.gz
Algorithm Hash digest
SHA256 fa3f56d6867a4fee9a0bb8fc67ca72a98de2f0c6450f6b6a17fae2c1d847c475
MD5 9c1cbbfcfbee62a75e91bab3f8be787a
BLAKE2b-256 6360b67e220c6ed0a7e6027b45fb86f3b0d3a838fa2c65b2b9715577c4d051a9

See more details on using hashes here.

Provenance

The following attestation bundles were made for tsujikiri-0.9.0.tar.gz:

Publisher: release.yml on kunitoki/tsujikiri

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tsujikiri-0.9.0-py3-none-any.whl.

File metadata

  • Download URL: tsujikiri-0.9.0-py3-none-any.whl
  • Upload date:
  • Size: 74.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tsujikiri-0.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1fb6bfb1fcaf3271e77c1e0e10b8caf67f7c9c98294388359d5b3160035b1205
MD5 80f1028cd8671f659cf2204a595b8d17
BLAKE2b-256 740cf099f77ad10cc73df2c7878ef7d5832b30352bf51059367439f79a6f50b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for tsujikiri-0.9.0-py3-none-any.whl:

Publisher: release.yml on kunitoki/tsujikiri

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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