easybind
Simple self-registering helpers for distributed nanobind bindings.
Install
pip install pymergetic-easybind
Platforms: PyPI ships manylinux (glibc 2.28+) and Windows amd64 wheels for CPython 3.11–3.14. macOS is not built in CI yet. On unsupported platforms pip may fall back to the sdist and require a local C++ toolchain.
import pymergetic.easybind
from pymergetic.easybind import sample # optional demo module
PyPI project: pymergetic-easybind (install name). Import: pymergetic.easybind.
Version: Set by Git tags at build time (v0.1.0, …) via setuptools-scm; see RELEASING.md. At runtime, pymergetic.easybind._version.__version__ is written when the wheel is built (or use importlib.metadata.version("pymergetic-easybind")).
Local dev / clangd
An editable install configures CMake under ./build/ and generates build/compile_commands.json, which clangd picks up via .clangd — same database as the Python build, no second configure step:
uv pip install -e . # or: pip install -e .
If you need compile_commands.json without pip, run scripts/clangd-update.sh (plain cmake -S . -B build …).
Python layer
The Python package is implemented as native extensions. It exposes:
pymergetic.easybind(core helpers and macros)pymergetic.easybind.module(module tree API)pymergetic.easybind.sample(demo bindings)
Build-time SDK
Installed wheels ship CMake helpers under pymergetic/easybind/cmake/:
easybind_pip.cmake—easybind_pip_setup()finds Python,nanobind(pip),libeasybind, and include roots for#include <pymergetic/easybind/...>, then pulls ineasybind_dependencies.cmake. Helpers:easybind_pip_link_magic_enum(target),easybind_pip_set_rpath_next_to_easybind(target easybind_pkg_dir).easybind_dependencies.cmake— pins nanobind, magic_enum, reflect-cpp (same tags as this repo). Useeasybind_fetch_third_party_deps()to pull all three, oreasybind_fetch_nanobind()/easybind_fetch_magic_enum()/easybind_fetch_reflect_cpp()when you only need a subset (e.g. pip already provides nanobind, so call onlyeasybind_fetch_magic_enum()).
Typical consumer bootstrap:
find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)
execute_process(COMMAND "${Python_EXECUTABLE}" -c
"import pathlib, pymergetic.easybind; print(pathlib.Path(pymergetic.easybind.__file__).resolve().parent / 'cmake' / 'easybind_pip.cmake')"
OUTPUT_VARIABLE _eb_pip OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY)
include("${_eb_pip}")
easybind_pip_setup()
easybind_fetch_magic_enum() # if you include easybind headers that need magic_enum
When developing inside this repository, easybind_add_extension(...) is defined in the top-level CMakeLists.txt (not shipped in the wheel).
Devtools (release / pin bumps)
Implemented in pymergetic.common.devtools (pymergetic-common). Install via pymergetic-easybind (depends on common) or uv sync.
pymergetic-pin-pyproject --project-root packages/easybind --dry-run
pymergetic-release-tag --project-root packages/easybind --dry-run
pymergetic-wait-pypi --project-root packages/easybind
See pymergetic-common RELEASING.md and from pymergetic.common.devtools import ….
Core idea
- Each namespace/module defines a
ModuleNodeand a bind callback. - The module entry point calls
apply_initto run the callback and recurse. - Submodules are created on demand and registered in
sys.modules. - Shared-object modules are marked so recursion stops at their boundary.
- A minimal sample module lives at
pymergetic.easybind.sample.
Developer note: layout rules
__init__.cppmarks the Python boundary (NB_MODULE) for a package/module.node.cpp/.hppis the pure C++ module-tree core.ns_module.hppdefines theEASYBIND_NS_MODULE*macros.- Directory layout mirrors namespaces and Python modules.
Smallest possible example
1) Define a C++ type (normal code)
#pragma once
#include <string>
struct PeerInfo {
std::string peer_id;
int transport = 0;
};
2) Bind it in a separate file (module node)
#include <pymergetic/easybind/bind.hpp>
struct PeerInfo; // forward declare or include the header
EASYBIND_NS_MODULE(my_pkg, m, false, {
nanobind::class_<PeerInfo>(m, "PeerInfo")
.def(nanobind::init<>())
.def_rw("peer_id", &PeerInfo::peer_id)
.def_rw("transport", &PeerInfo::transport);
});
3) Module entry point (shared-object boundary)
Use this only for the package that has its own .so and NB_MODULE entry point.
Do not pair it with EASYBIND_NS_MODULE for the same my_pkg name.
If you need to add bindings from another file, use EASYBIND_NS_MODULE_EXTEND
to extend the same module node instead.
#include <pymergetic/easybind/bind.hpp>
EASYBIND_NS_MODULE_SHARED_OBJECT(my_pkg, my_pkg, m, true, {
m.doc() = "my_pkg module";
});
4) Extend from another file
#include <pymergetic/easybind/bind.hpp>
EASYBIND_NS_MODULE_EXTEND(my_pkg, m, {
m.def("ping", [] { return "pong"; });
});
Metadata
Release files for pymergetic-easybind 0.3.20
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pymergetic_easybind-0.3.20.tar.gz | 53.5 kB | Details |
Built distributions (wheels)
Total release size: 3.8 MB
Release files / pymergetic_easybind-0.3.20.tar.gz
| Download URL | pymergetic_easybind-0.3.20.tar.gz |
|---|---|
| Size | 53.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bcc139fba718355cc924e3969cf106eac3b3ed8565ae1aa9b4084269ab7eeb6b
|
|
BLAKE2b-256 checksum How to use checksums |
355248ad855a751409a383c038c0636b5b94c4e25c289db17e0eabffd7551bf8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / pymergetic_easybind-0.3.20-cp314-cp314-win_amd64.whl
| Download URL | pymergetic_easybind-0.3.20-cp314-cp314-win_amd64.whl |
|---|---|
| Size | 651.2 kB |
| Tags | CPython 3.14 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
5445077f51ec3e0a5c961092a0d2d47ff6e33a53568778f30662ce2a2c1540d6
|
|
BLAKE2b-256 checksum How to use checksums |
45fc0b13944b17427f69ef1e6cbb2ec5b029119946e81dec3ab495ac0e66ba6f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / pymergetic_easybind-0.3.20-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | pymergetic_easybind-0.3.20-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 295.9 kB |
| Tags | CPython 3.14 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
b9e2082938b3ac2d11bd4381dd5d797ff9afbc60a253d2975512c54ffcd51ffa
|
|
BLAKE2b-256 checksum How to use checksums |
c50683395bfcd1a738eba4bf4e1fc196b68146c52e11fe2698ef3c4889fe7bf2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / pymergetic_easybind-0.3.20-cp313-cp313-win_amd64.whl
| Download URL | pymergetic_easybind-0.3.20-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 638.5 kB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
d5e740dc94cae89a3fe7ce75f090db5b7e401294b661a688793e52c383bf51f4
|
|
BLAKE2b-256 checksum How to use checksums |
1af20c422d6cf85cd98bb3edf511a8191c36df200682e6bb8cd12a6bdf613d32
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / pymergetic_easybind-0.3.20-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | pymergetic_easybind-0.3.20-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 295.9 kB |
| Tags | CPython 3.13 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
116e3dd3b2c94dc178164fa9d28ed78bb12efbdc47f5791c5c29d8c466dedd1d
|
|
BLAKE2b-256 checksum How to use checksums |
cd06523f56f41a9a56a58536f52b6da3c1d94cd98284df3eba43a9c5db241a4d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / pymergetic_easybind-0.3.20-cp312-cp312-win_amd64.whl
| Download URL | pymergetic_easybind-0.3.20-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 639.4 kB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
64df5ea0def61ab35abd8cc817b5426631c7e760d3cca099979aa0dd0f2ecefa
|
|
BLAKE2b-256 checksum How to use checksums |
4c1ad21931c6d90897865f988906028d3d3317ffa4fc50bf168959f188bf25b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / pymergetic_easybind-0.3.20-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | pymergetic_easybind-0.3.20-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 295.8 kB |
| Tags | CPython 3.12 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
2ae5b54a78a132ca0c4e44cf42a1f0025b2293f847eb71b5e479ff3b0840e3ed
|
|
BLAKE2b-256 checksum How to use checksums |
3b9a7c8d9c66810ef463e498cbb84d8fe06402390600f5fda9ae2f9471757c12
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / pymergetic_easybind-0.3.20-cp311-cp311-win_amd64.whl
| Download URL | pymergetic_easybind-0.3.20-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 640.6 kB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
0745f814c9c5ec2b71831c85071c2aedb0ac4e2bf3f37f75bafd09992a775057
|
|
BLAKE2b-256 checksum How to use checksums |
a2517df9073e0f3424ad2655971863bea06c64851937030d4cfa3de211347c39
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / pymergetic_easybind-0.3.20-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | pymergetic_easybind-0.3.20-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 296.3 kB |
| Tags | CPython 3.11 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
e06d2cbf707295ab6b7989e4569c0c42c1977ef40c432f6d532ed3acfce01a3d
|
|
BLAKE2b-256 checksum How to use checksums |
188fadac27696d0af4d6e40ffaaf95b9b8c161e8fcea3f19ec681e87b8b0f767
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|