### Install Meson dependencies Source: https://github.com/wjakob/nanobind/blob/master/docs/meson.md Initialize the subprojects directory and install required wrap packages. ```sh mkdir -p subprojects meson wrap install robin-map meson wrap install nanobind ``` -------------------------------- ### Compile and install extension Source: https://github.com/wjakob/nanobind/blob/master/docs/meson.md Commands to build the extension or perform an editable install. ```sh meson setup --buildtype release builddir meson compile -C builddir ``` ```sh python -m pip install -e . ``` -------------------------------- ### Install Project Files and Directories Source: https://github.com/wjakob/nanobind/blob/master/CMakeLists.txt Rules for installing include directories, source files, and specific dependencies. ```cmake install( DIRECTORY include/ DESTINATION "${NB_INSTALL_INC_DIR}" ) install( DIRECTORY src/ DESTINATION "${NB_INSTALL_SRC_DIR}" PATTERN "*.py" EXCLUDE ) install( DIRECTORY src/ DESTINATION "${NB_INSTALL_MODULE_DIR}" FILES_MATCHING PATTERN "*\.py" PATTERN "version.py" EXCLUDE ) if(NB_USE_SUBMODULE_DEPS) install( FILES ext/robin_map/include/tsl/robin_map.h ext/robin_map/include/tsl/robin_hash.h ext/robin_map/include/tsl/robin_growth_policy.h DESTINATION "${NB_INSTALL_EXT_DIR}/robin_map/include/tsl" ) endif() install( FILES cmake/nanobind-config.cmake cmake/darwin-python-path.py cmake/darwin-ld-cpython.sym cmake/darwin-ld-pypy.sym DESTINATION "${NB_INSTALL_CMAKE_DIR}" ) ``` -------------------------------- ### Define Installation Rules Source: https://github.com/wjakob/nanobind/blob/master/CMakeLists.txt Sets the installation directory for nanobind data files when installation rules are enabled. ```cmake if(NB_CREATE_INSTALL_RULES AND NOT CMAKE_SKIP_INSTALL_RULES) set(NB_INSTALL_DATADIR "nanobind" CACHE PATH "Installation path for read-only architecture-independent nanobind data files") # Normally these would be configurable by the user, but we can't allow that ``` -------------------------------- ### Define Installation Directories Source: https://github.com/wjakob/nanobind/blob/master/CMakeLists.txt Sets the base installation paths for nanobind components based on the data directory. ```cmake set(NB_INSTALL_INC_DIR "${NB_INSTALL_DATADIR}/include") set(NB_INSTALL_SRC_DIR "${NB_INSTALL_DATADIR}/src") set(NB_INSTALL_EXT_DIR "${NB_INSTALL_DATADIR}/ext") set(NB_INSTALL_MODULE_DIR "${NB_INSTALL_DATADIR}") set(NB_INSTALL_CMAKE_DIR "${NB_INSTALL_DATADIR}/cmake") ``` -------------------------------- ### Verify extension installation Source: https://github.com/wjakob/nanobind/blob/master/docs/packaging.md Import the compiled extension module and execute its functions to verify successful installation. ```python >>> import my_ext >>> my_ext.hello() 'Hello world!' ``` -------------------------------- ### Install nanobind via Conda Source: https://github.com/wjakob/nanobind/blob/master/docs/installing.md Provides an alternative installation method for users developing Conda-based extensions with build-time dependencies. ```bash conda install -c conda-forge nanobind ``` -------------------------------- ### Install package locally Source: https://github.com/wjakob/nanobind/blob/master/docs/packaging.md Use pip to install the project in the current directory, which triggers dependency resolution via pyproject.toml. ```bash $ cd $ pip install . ``` -------------------------------- ### Generate and Install Package Version File Source: https://github.com/wjakob/nanobind/blob/master/CMakeLists.txt Creates a version file for the CMake package and installs it to the configuration directory. ```cmake include(CMakePackageConfigHelpers) write_basic_package_version_file( ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake COMPATIBILITY SameMajorVersion ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake DESTINATION "${NB_INSTALL_CMAKE_DIR}" ) ``` -------------------------------- ### Compile and install the extension module Source: https://github.com/wjakob/nanobind/blob/master/docs/packaging.md Uses nanobind_add_module to define the extension and sets the install destination for scikit-build-core. ```cmake # We are now ready to compile the actual extension module nanobind_add_module( # Name of the extension _my_ext_impl # Target the stable ABI for Python 3.12+, which reduces # the number of binary wheels that must be built. This # does nothing on older Python versions STABLE_ABI # Source code goes here src/my_ext.cpp ) # Install directive for scikit-build-core install(TARGETS _my_ext_impl LIBRARY DESTINATION my_ext) ``` -------------------------------- ### Install build dependencies Source: https://github.com/wjakob/nanobind/blob/master/docs/packaging.md Manually install required build-time dependencies to prepare for incremental build workflows. ```bash $ pip install nanobind scikit-build-core[pyproject] ``` -------------------------------- ### Install nanobind via Pip Source: https://github.com/wjakob/nanobind/blob/master/docs/installing.md Installs the package containing the necessary C++ and CMake source code for extension modules. ```bash python -m pip install nanobind ``` -------------------------------- ### Launch interactive Python session Source: https://github.com/wjakob/nanobind/blob/master/docs/basics.md Navigate to the build directory and start a Python interpreter to test the extension. ```bash cd build python3 ``` -------------------------------- ### Viewing help for a bound class Source: https://github.com/wjakob/nanobind/blob/master/docs/functions.md Example output showing how default arguments appear in Python help documentation. ```pycon >> help(my_ext.MyClass) class MyClass(builtins.object) | Methods defined here: .... | f(...) | f(self, value: my_ext.SomeType = ) -> None ``` -------------------------------- ### Generate wheel file Source: https://github.com/wjakob/nanobind/blob/master/docs/packaging.md Create a distribution wheel file instead of performing a direct installation. ```bash $ pip wheel . ``` -------------------------------- ### Install generated stub files Source: https://github.com/wjakob/nanobind/blob/master/docs/typing.md Use standard CMake install directives to deploy the compiled module and generated stub files. ```cmake install(TARGETS my_ext DESTINATION ".") install(FILES py.typed my_ext.pyi DESTINATION ".") ``` -------------------------------- ### Install Python development headers Source: https://github.com/wjakob/nanobind/blob/master/docs/basics.md Install the necessary Python development package on Ubuntu if CMake fails to locate Python. ```bash apt install libpython3-dev ``` -------------------------------- ### Define function bindings with keywords and defaults Source: https://github.com/wjakob/nanobind/blob/master/docs/basics.md Complete C++ example showing how to bind a function with default arguments, keyword annotations, and a docstring. ```cpp #include namespace nb = nanobind; using namespace nb::literals; int add(int a, int b = 1) { return a + b; } NB_MODULE(my_ext, m) { m.def("add", &add, "a"_a, "b"_a = 1, "This function adds two numbers and increments if only one is provided."); } ``` -------------------------------- ### Define a C++ function and module binding Source: https://github.com/wjakob/nanobind/blob/master/docs/functions.md Initial setup for a function that accepts a pointer and a module definition. ```cpp struct Dog { }; const char *bark(Dog *dog) { return dog != nullptr ? "woof!" : "(no dog)"; } NB_MODULE(my_ext, m) { nb::class_(m, "Dog") .def(nb::init<>()); m.def("bark", &bark); } ``` -------------------------------- ### Generate stubs at install time Source: https://github.com/wjakob/nanobind/blob/master/docs/typing.md Use the INSTALL_TIME parameter to delay stub generation until the installation phase, which is useful when the module is not importable during the build phase. ```cmake install(TARGETS my_ext DESTINATION ".") nanobind_add_stub( my_ext_stub INSTALL_TIME MODULE my_ext OUTPUT my_ext.pyi PYTHON_PATH "." ) ``` -------------------------------- ### Define a string-based enumeration Source: https://github.com/wjakob/nanobind/blob/master/docs/classes.md Example of creating a StrEnum using nb::is_str() and registering entries with .str_value(). ```cpp nb::enum_(m, "Color", nb::is_str()) .str_value("Red", Color::Red, "red") .str_value("Green", Color::Green, "green") .str_value("Blue", Color::Blue, "blue"); ``` -------------------------------- ### Example stub replacement Source: https://github.com/wjakob/nanobind/blob/master/docs/typing.md Replace a lackluster stub entry with typed overloads. ```python class MyClass: def my_function(arg: object) -> object: ... ``` ```text my_ext.MyClass.my_function: @overload def my_function(arg: int) -> int: """A helpful docstring""" @overload def my_function(arg: str) -> str: ... ``` -------------------------------- ### Python Exception Chaining Example Source: https://github.com/wjakob/nanobind/blob/master/docs/exceptions.md Demonstrates the standard Python syntax for raising an exception from a previous one. ```python try: print(1 / 0) except Exception as exc: raise RuntimeError("could not divide by zero") from exc ``` -------------------------------- ### Define a Singleton Class Source: https://github.com/wjakob/nanobind/blob/master/docs/classes.md Example of a C++ class intended to be managed as a singleton. ```cpp class Singleton { public: static Singleton &get_instance(); }; ``` -------------------------------- ### Install nanobind as a Git submodule Source: https://github.com/wjakob/nanobind/blob/master/docs/installing.md Adds the library directly to your repository, useful for projects avoiding external package managers. ```bash git submodule add https://github.com/wjakob/nanobind ext/nanobind git submodule update --init --recursive ``` -------------------------------- ### Bind Arithmetic Operators Source: https://github.com/wjakob/nanobind/blob/master/docs/api_core.md Example showing C++ arithmetic operator definitions and their corresponding nanobind bindings. ```cpp struct A { float value; A operator-() const { return { -value }; } A operator-(const A &o) const { return { value - o.value }; } A operator-(float o) const { return { value - o }; } }; nb::class_(m, "A") .def(nb::init()) .def(-nb::self) .def(nb::self - nb::self) .def(nb::self - float()); ``` -------------------------------- ### Enable automatic rebuilds Source: https://github.com/wjakob/nanobind/blob/master/docs/packaging.md Configure the installation to automatically trigger a rebuild upon importing the package in a Python session. ```bash $ pip install --no-build-isolation -Ceditable.rebuild=true -ve . ``` -------------------------------- ### Perform incremental rebuilds Source: https://github.com/wjakob/nanobind/blob/master/docs/packaging.md Install the project without build isolation to allow for faster, incremental updates after source code changes. ```bash $ pip install --no-build-isolation -ve . ``` -------------------------------- ### Bind a C++ class and methods Source: https://github.com/wjakob/nanobind/blob/master/docs/api_core.md Example showing how to expose a C++ struct to Python with a constructor and a member function. ```cpp struct A { void f() { /*...*/ } }; nb::class_(m, "A") .def(nb::init<>()) // Bind the default constructor .def("f", &A::f); // Bind the method A::f ``` -------------------------------- ### Configure enumeration with arithmetic support Source: https://github.com/wjakob/nanobind/blob/master/docs/classes.md Example of enabling arithmetic operations for an enumeration using the nb::is_arithmetic() annotation. ```cpp nb::enum_(pet, "Kind", nb::is_arithmetic()) ... ``` -------------------------------- ### Configure build system with CMake Source: https://github.com/wjakob/nanobind/blob/master/docs/basics.md Initialize the build directory using CMake. ```bash cmake -S . -B build ``` -------------------------------- ### Initialize Benchmarking Environment Source: https://github.com/wjakob/nanobind/blob/master/docs/microbenchmark.ipynb Imports necessary libraries and configures matplotlib settings for visualization. ```python import random import subprocess import itertools from collections import defaultdict import importlib.machinery import os import time import cython from matplotlib.patches import Rectangle import matplotlib.pyplot as plt import numpy as np import matplotlib as mpl mpl.rcParams['hatch.linewidth'] = 5.0 cycle = [x['color'] for x in mpl.rcParams['axes.prop_cycle']] ``` -------------------------------- ### Define a basic class binding Source: https://github.com/wjakob/nanobind/blob/master/docs/typing.md Initial class binding example that may cause type checking issues due to default signature generation. ```cpp nb::class_(m, "Int") .def(nb::self == nb::self); ``` -------------------------------- ### Mark instance as ready Source: https://github.com/wjakob/nanobind/blob/master/docs/lowlevel.md Inform nanobind that the instance is fully constructed and ready for use. ```cpp nb::inst_mark_ready(py_inst); assert(nb::inst_ready(py_inst)); ``` -------------------------------- ### Implement a custom call policy with postcall Source: https://github.com/wjakob/nanobind/blob/master/docs/api_core.md This example demonstrates a custom call policy that tracks references between a returned sequence and a function argument, similar to nb::keep_alive. ```cpp template struct returns_references_to { static void precall(PyObject **, size_t, nb::detail::cleanup_list *) {} template static void postcall(PyObject **args, std::integral_constant, nb::handle ret) { static_assert(I > 0 && I <= N, "I in returns_references_to must be in the " "range [1, number of C++ function arguments]"); if (!nb::isinstance(ret)) { throw std::runtime_error("return value should be a sequence"); } for (nb::handle nurse : ret) { nb::detail::keep_alive(nurse.ptr(), args[I - 1]); } } }; ``` -------------------------------- ### inst_ready Source: https://github.com/wjakob/nanobind/blob/master/docs/api_core.md Queries the ready flag of an instance. ```APIDOC ## inst_ready(handle h) ### Description Query the ready flag of the instance `h`. ``` -------------------------------- ### View stubgen command line options Source: https://github.com/wjakob/nanobind/blob/master/docs/typing.md Displays the help menu for the nanobind stub generator CLI. ```text usage: python -m nanobind.stubgen [-h] [-o FILE] [-O PATH] [-i PATH] [-m MODULE] [-r] [-M FILE] [-P] [-D] [--exclude-values] [-q] Generate stubs for nanobind-based extensions. options: -h, --help show this help message and exit -o FILE, --output-file FILE write generated stubs to the specified file -O PATH, --output-dir PATH write generated stubs to the specified directory -i PATH, --import PATH add the directory to the Python import path (can specify multiple times) -m MODULE, --module MODULE generate a stub for the specified module (can specify multiple times) -r, --recursive recursively process submodules -M FILE, --marker-file FILE generate a marker file (usually named 'py.typed') -p FILE, --pattern-file FILE apply the given patterns to the generated stub (see the docs for syntax) -P, --include-private include private members (with single leading or trailing underscore) -D, --exclude-docstrings exclude docstrings from the generated stub --exclude-values force the use of ... for values -q, --quiet do not generate any output in the absence of failures ``` -------------------------------- ### Bind constructors with nb::init Source: https://github.com/wjakob/nanobind/blob/master/docs/api_core.md Demonstrates the use of nb::init as syntax sugar for placement new in C++ class bindings. ```cpp nb::class_(m, "MyType") .def(nb::init()); ``` ```cpp nb::class_(m, "MyType") .def("__init__", [](MyType* t, const char* arg0, int arg1) { new (t) MyType(arg0, arg1); }); ``` -------------------------------- ### Define Templated Classes Source: https://github.com/wjakob/nanobind/blob/master/docs/classes.md Example of C++ classes with template parameters. ```cpp struct Cat {}; struct Dog {}; template struct PetHouse { PetHouse(PetType& pet); PetType& get(); }; ``` -------------------------------- ### Viewing module documentation in Python Source: https://github.com/wjakob/nanobind/blob/master/docs/basics.md Demonstrates how to access the module documentation using the help() builtin in an interactive Python session. ```pycon >>> import my_ext >>> help(my_ext) Help on module my_ext: NAME my_ext - A simple example python extension DATA add = add(a: int, b: int = 1) -> int This function adds two numbers and increments if only one is provided the_answer = 42 FILE /Users/wjakob/my_ext/my_ext.cpython-311-darwin.so ``` -------------------------------- ### Zero-initialize POD types Source: https://github.com/wjakob/nanobind/blob/master/docs/lowlevel.md Zero-initialize a POD instance and mark it as ready. ```cpp nb::inst_zero(py_inst); assert(nb::inst_ready(py_inst)); ``` -------------------------------- ### Python usage of bound functions Source: https://github.com/wjakob/nanobind/blob/master/docs/basics.md Example of calling the bound higher-order function in Python. ```pycon >>> f = d.bark_later() >>> f >>> f() Charlie: woof! ``` -------------------------------- ### Define struct-based binding Source: https://github.com/wjakob/nanobind/blob/master/docs/benchmark.md Example of packaging the same arithmetic computation into a struct with associated bindings. ```cpp struct Struct50 { uint16_t a; int64_t b; int32_t c; uint64_t d; uint32_t e; float f; Struct50(uint16_t a, int64_t b, int32_t c, uint64_t d, uint32_t e, float f) : a(a), b(b), c(c), d(d), e(e), f(f) { } float sum() const { return a+b+c+d+e+f; } }; py::class_(m, "Struct50") .def(py::init()) .def("sum", &Struct50::sum); ``` -------------------------------- ### Initialize nanobind project Source: https://github.com/wjakob/nanobind/blob/master/CMakeLists.txt Checks project status and enables C++ language support. ```cmake if (NB_MASTER_PROJECT AND NOT NB_TEST) return() else() enable_language(CXX) endif() ``` -------------------------------- ### Define higher-order functions Source: https://github.com/wjakob/nanobind/blob/master/docs/functions.md Examples of C++ functions that accept or return std::function objects. ```cpp int func_arg(const std::function &f) { return f(10); } ``` ```cpp std::function func_ret(const std::function &f) { return [f](int i) { return f(i) + 1; }; } ``` -------------------------------- ### Define Non-Polymorphic Class Hierarchy Source: https://github.com/wjakob/nanobind/blob/master/docs/classes.md Setup for a class hierarchy using an enum for tag-based identification. ```cpp #include namespace nb = nanobind; enum class PetKind { Cat, Dog }; struct Pet { const PetKind kind; }; struct Dog : Pet { Dog() : Pet{PetKind::Dog} { } }; struct Cat : Pet { Cat() : Pet{PetKind::Cat} { } }; namespace nb = nanobind; NB_MODULE(my_ext, m) { nb::class_(m, "Pet"); nb::class_(m, "Dog"); nb::class_(m, "Cat"); nb::enum_(m, "PetKind") .value("Cat", PetKind::Cat) .value("Dog", PetKind::Dog); m.def("make_pet", [](PetKind kind) -> Pet* { switch (kind) { case PetKind::Dog: return new Dog(); case PetKind::Cat: return new Cat(); } }); } ``` -------------------------------- ### Configure scikit-build-core settings Source: https://github.com/wjakob/nanobind/blob/master/docs/packaging.md Set recommended defaults for build directories and ABI compatibility. ```toml [tool.scikit-build] # Protect the configuration against future changes in scikit-build-core minimum-version = "0.4" # Setuptools-style build caching in a local directory build-dir = "build/{wheel_tag}" # Build stable ABI wheels for CPython 3.12+ wheel.py-api = "cp312" ``` -------------------------------- ### Set up nanobind namespace alias Source: https://github.com/wjakob/nanobind/blob/master/docs/basics.md Standard practice to alias the nanobind namespace for cleaner binding code. ```cpp namespace nb = nanobind; ``` -------------------------------- ### Define C++ nested types and enumerations Source: https://github.com/wjakob/nanobind/blob/master/docs/classes.md Example C++ structure containing an enum and a nested struct. ```cpp struct Pet { enum Kind { Dog = 0, Cat }; struct Attributes { float age = 0; }; Pet(const std::string &name, Kind type) : name(name), type(type) { } std::string name; Kind type; Attributes attr; }; ``` -------------------------------- ### Compile the extension Source: https://github.com/wjakob/nanobind/blob/master/docs/basics.md Build the extension using the configured CMake build system. ```bash cmake --build build ``` -------------------------------- ### Parameterize a Python list type Source: https://github.com/wjakob/nanobind/blob/master/docs/typing.md Example of a Python function signature using a parameterized list type. ```python def f() -> list[int]: ... a = f()[0] ``` -------------------------------- ### Comparing function binding overheads Source: https://github.com/wjakob/nanobind/blob/master/docs/functions.md Demonstrates the difference between a fast-path function binding (f1) and a standard binding (f2) that includes keyword arguments. ```cpp NB_MODULE(my_ext, m) { m.def("f1", [](int) { /* no-op */ }); m.def("f2", [](int) { /* no-op */ }, "arg"_a); } ``` -------------------------------- ### Call inspect function from Python Source: https://github.com/wjakob/nanobind/blob/master/docs/ndarray.md Example usage of the bound inspect function with a NumPy array input. ```pycon >>> my_module.inspect(np.array([[1,2,3], [3,4,5]], dtype=np.float32)) Array data pointer : 0x1c30f60 Array dimension : 2 Array dimension [0] : 2 Array stride [0] : 3 Array dimension [1] : 3 Array stride [1] : 1 Device ID = 0 (cpu=1, cuda=0) Array dtype: int16=0, uint32=0, float32=1 ``` -------------------------------- ### Detecting type conflicts Source: https://github.com/wjakob/nanobind/blob/master/docs/faq.md Example of the runtime warning generated when nanobind detects a type registration conflict. ```text RuntimeWarning: nanobind: type 'latch' was already registered! ``` -------------------------------- ### Define a basic nanobind extension Source: https://github.com/wjakob/nanobind/blob/master/docs/basics.md Create a C++ file to define a module and expose a function to Python. ```cpp #include int add(int a, int b) { return a + b; } NB_MODULE(my_ext, m) { m.def("add", &add); } ``` -------------------------------- ### Define a thread-unsafe Counter class Source: https://github.com/wjakob/nanobind/blob/master/docs/free_threaded.md This example demonstrates a class with an increment operation that is not thread-safe when accessed concurrently. ```cpp struct Counter { int value = 0; void inc() { value++; } }; nb::class_(m, "Counter") .def("inc", &Counter::inc) .def_ro("value", &Counter::value); ``` -------------------------------- ### Partitioning nanobind projects Source: https://github.com/wjakob/nanobind/blob/master/docs/faq.md Split large binding projects into multiple files to improve build performance and incremental compilation. ```cpp void init_ex1(nb::module_ &); void init_ex2(nb::module_ &); /* ... */ NB_MODULE(my_ext, m) { init_ex1(m); init_ex2(m); /* ... */ } ``` ```cpp void init_ex1(nb::module_ &m) { m.def("add", [](int a, int b) { return a + b; }); } ``` ```cpp void init_ex2(nb::module_ &m) { m.def("sub", [](int a, int b) { return a - b; }); } ``` -------------------------------- ### Python to C++ parameter passing Source: https://github.com/wjakob/nanobind/blob/master/docs/eigen.md Examples of different ways to pass Eigen matrices from Python to C++. ```cpp void f1(const Eigen::MatrixXf &x) { ... } void f2(const Eigen::Ref &x) { ... } void f3(const nb::DRef &x) { ... } ``` ```cpp m.def("f1", &f1, nb::arg("x").noconvert()); ``` ```cpp void f4(nb::DRef x) { x *= 2; } ``` -------------------------------- ### Return Eigen matrix by value Source: https://github.com/wjakob/nanobind/blob/master/docs/eigen.md Example of a C++ function returning a dense Eigen matrix to Python. ```cpp Eigen::MatrixXf f() { ... } ``` -------------------------------- ### Create nanobind module bindings Source: https://github.com/wjakob/nanobind/blob/master/docs/basics.md Full module definition exposing the Dog struct with constructors, methods, and read/write fields. ```cpp #include #include namespace nb = nanobind; NB_MODULE(my_ext, m) { nb::class_(m, "Dog") .def(nb::init<>()) .def(nb::init()) .def("bark", &Dog::bark) .def_rw("name", &Dog::name); } ``` -------------------------------- ### Implementing Pickling Support Source: https://github.com/wjakob/nanobind/blob/master/docs/classes.md Exposes __getstate__ and __setstate__ to enable object serialization. Use in-place construction for __setstate__. ```cpp #include struct Pet { std::string name; int age; Pet(const std::string &name, int age) : name(name), age(age) { } }; NB_MODULE(my_ext, m) { nb::class_(m, "Pet") // ... .def("__getstate__", [](const Pet &pet) { return std::make_tuple(pet.name, pet.age); }) .def("__setstate__", [](Pet &pet, const std::tuple &state) { new (&pet) Pet( std::get<0>(state), std::get<1>(state) ); }); } ``` -------------------------------- ### Example of unsafe reference usage Source: https://github.com/wjakob/nanobind/blob/master/docs/api_extra.md Demonstrates how using reference semantics can lead to crashes when the underlying vector is modified. ```python def looks_fine_but_crashes(vec: ext.ExampleVec) -> None: # Trying to remove all the elements too much older than the last: last = vec[-1] # Even being careful to iterate backwards so we visit each # index only once... for idx in range(len(vec) - 2, -1, -1): if last.timestamp - vec[idx].timestamp > 5: del vec[idx] # Oops! After the first deletion, 'last' now refers to # uninitialized memory. ``` -------------------------------- ### class_::def (init) Source: https://github.com/wjakob/nanobind/blob/master/docs/api_core.md Binds a constructor to a class. ```APIDOC ## def(init arg, const Extra&... extra) ### Description Binds a constructor for the class. ### Parameters - **arg** (init) - Required - The constructor definition. - **extra** (Extra...) - Optional - Variable length parameter for docstrings and binding annotations. ``` -------------------------------- ### Verify Trampoline Functionality in Python Source: https://github.com/wjakob/nanobind/blob/master/docs/classes.md Example of calling a bound method that utilizes a trampoline to execute Python-side overrides. ```pycon >>> my_ext.alarm(dog) Mr. Fluffles: yip! Mr. Fluffles: yip! Mr. Fluffles: yip! ``` -------------------------------- ### Define meson.build for extension module Source: https://github.com/wjakob/nanobind/blob/master/docs/meson.md Basic configuration for building a C++ extension module using nanobind. ```meson project( 'my_project_name', 'cpp', version: '0.0.1', meson_version: '>=1.0.0', default_options: ['cpp_std=c++17', 'b_ndebug=if-release'], ) python = import('python').find_installation() nanobind_dep = dependency('nanobind') mod = python.extension_module( 'my_module_name', sources: ['path_to_module.cpp'], dependencies: [nanobind_dep], install: true, ) ``` -------------------------------- ### Define build-system requirements Source: https://github.com/wjakob/nanobind/blob/master/docs/packaging.md Specify the build backend and required dependencies for the project. ```toml [build-system] requires = ["scikit-build-core >=0.4.3", "nanobind >=1.3.2"] build-backend = "scikit_build_core.build" ``` -------------------------------- ### Interact with bound types in Python Source: https://github.com/wjakob/nanobind/blob/master/docs/classes.md Example usage of the bound Pet class and its nested Kind enumeration in Python. ```pycon >>> from my_ext import Pet >>> p = Pet("Lucy", Pet.Cat) >>> p.attr.age = 3 >>> p.type my_ext.Kind.Cat >>> p.type.__name__ 'Cat' ``` -------------------------------- ### Define an iterable vector binding Source: https://github.com/wjakob/nanobind/blob/master/docs/typing.md Example of a class binding that requires better type information for static analysis. ```cpp using IntVec = std::vector; nb::class_(m, "IntVec") .def("__iter__", [](const IntVec &v) -> GeneralIterator { ... }) ``` -------------------------------- ### Compare nanobind_add_module with low-level interface Source: https://github.com/wjakob/nanobind/blob/master/docs/api_cmake.md Demonstrates the equivalence between the high-level nanobind_add_module command and the manual sequence of low-level CMake calls. ```cmake nanobind_add_module(my_ext NB_SHARED LTO my_ext.cpp) ``` ```cmake # Build the core parts of nanobind once nanobind_build_library(nanobind SHARED) # Compile an extension library add_library(my_ext MODULE my_ext.cpp) # .. and link it against the nanobind parts target_link_libraries(my_ext PRIVATE nanobind) # .. enable size optimizations nanobind_opt_size(my_ext) # .. enable link time optimization nanobind_lto(my_ext) # .. set the default symbol visibility to 'hidden' nanobind_set_visibility(my_ext) # .. strip unneeded symbols and debug info from the binary (only active in release builds) nanobind_strip(my_ext) # .. disable the stack protector nanobind_disable_stack_protector(my_ext) # .. set the Python extension suffix nanobind_extension(my_ext) # .. set important compilation flags nanobind_compile_options(my_ext) # .. set important linker flags nanobind_link_options(my_ext) # Statically link against libstdc++/libgcc when targeting musllinux nanobind_musl_static_libcpp(my_ext) ``` -------------------------------- ### Example of an ndarray TypeError Source: https://github.com/wjakob/nanobind/blob/master/docs/ndarray.md Shows the error message generated when calling a function with an ndarray that does not meet the defined constraints. ```pycon >>> my_module.process(np.zeros(1)) TypeError: process(): incompatible function arguments. The following argument types are supported: 1. process(arg: ndarray[dtype=uint8, shape=(*, *, 3), device='cpu'], /) -> None Invoked with types: numpy.ndarray ``` -------------------------------- ### Construct instance in-place Source: https://github.com/wjakob/nanobind/blob/master/docs/lowlevel.md Use placement new to construct a C++ object within the memory allocated by nanobind. ```cpp // Get a C++ pointer to the uninitialized instance data MyClass *ptr = nb::inst_ptr(py_inst); // Perform an in-place construction of the C++ object at address 'ptr' new (ptr) MyClass(/* constructor arguments go here */); ``` -------------------------------- ### init Source: https://github.com/wjakob/nanobind/blob/master/docs/api_core.md A helper class used to capture the signature of a C++ constructor for binding declarations. ```APIDOC ## template struct init ### Description Used within `class_::def()` to bind existing C++ constructors to Python. It captures the constructor signature to facilitate object initialization. ``` -------------------------------- ### Demonstrate Python reference cycles Source: https://github.com/wjakob/nanobind/blob/master/docs/refleaks.md Example showing how a self-referencing list maintains a reference count of 1 after deletion. ```python l = [] # 'l' ref. count = 1 l.append(l) # 'l' ref. count = 2 del l # 'l' ref. count = 1 ``` -------------------------------- ### Copy or move uninitialized nanobind instances Source: https://github.com/wjakob/nanobind/blob/master/docs/lowlevel.md Use these functions to initialize a destination object from a source instance. The destination must be uninitialized. ```cpp if (copy_instance) nb::inst_copy(/* dst = */ py_inst, /* src = */ some_other_instance); else nb::inst_move(/* dst = */ py_inst, /* src = */ some_other_instance); ``` -------------------------------- ### Demonstrate keyword argument failure Source: https://github.com/wjakob/nanobind/blob/master/docs/basics.md Example of a TypeError occurring when calling a function with keyword arguments that were not explicitly bound. ```pycon >>> my_ext.add(a=1, b=2) TypeError: add(): incompatible function arguments. The following argument types are supported: 1. add(arg0: int, arg1: int, /) -> int Invoked with types: kwargs = { a: int, b: int } ``` -------------------------------- ### Configure pyproject.toml for Meson Source: https://github.com/wjakob/nanobind/blob/master/docs/meson.md Define the build system requirements and backend for a Meson-based Python project. ```toml [project] name = "my_project_name" dynamic = ['version'] [build-system] requires = ['meson-python'] build-backend = 'mesonpy' ``` -------------------------------- ### Increment function with reference argument Source: https://github.com/wjakob/nanobind/blob/master/docs/faq.md Example of a C++ function using a mutable reference that will not propagate updates to Python. ```cpp void increment(int &i) { i++; } ``` -------------------------------- ### Diagnose module import errors Source: https://github.com/wjakob/nanobind/blob/master/docs/faq.md Example of an ImportError caused by a mismatch between the module name in CMake and the NB_MODULE macro. ```pycon >>> import my_ext ImportError: dynamic module does not define module export function (PyInit_my_ext) ``` -------------------------------- ### Global Configuration Flags Source: https://github.com/wjakob/nanobind/blob/master/docs/api_core.md Functions to get and set global nanobind behavior regarding warnings and library liveness. ```APIDOC ## Global Flags ### bool leak_warnings() noexcept Returns whether nanobind warns about alive instances during interpreter shutdown. ### bool implicit_cast_warnings() noexcept Returns whether nanobind warns about unsuccessful implicit conversions. ### void set_leak_warnings(bool value) noexcept Enables or disables leak warnings. ### void set_implicit_cast_warnings(bool value) noexcept Enables or disables implicit cast warnings. ### inline bool is_alive() noexcept Returns true if nanobind is initialized and ready for use. ``` -------------------------------- ### Define build options and test configuration Source: https://github.com/wjakob/nanobind/blob/master/CMakeLists.txt Sets project options and conditional flags for testing, sanitizers, and dependency management. ```cmake if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(NB_MASTER_PROJECT ON) else() set(NB_MASTER_PROJECT OFF) endif() option(NB_CREATE_INSTALL_RULES "Create installation rules" ${NB_MASTER_PROJECT}) option(NB_USE_SUBMODULE_DEPS "Use the nanobind dependencies shipped as a git submodule of this repository" ON) option(NB_TEST "Compile nanobind tests?" ${NB_MASTER_PROJECT}) option(NB_TEST_STABLE_ABI "Test the stable ABI interface?" OFF) option(NB_TEST_SHARED_BUILD "Build a shared nanobind library for the test suite?" OFF) option(NB_TEST_CUDA "Force the use of the CUDA/NVCC compiler for testing purposes" OFF) option(NB_TEST_FREE_THREADED "Build free-threaded extensions for the test suite?" ON) if (NOT MSVC) option(NB_TEST_SANITIZERS_ASAN "Build tests with the address sanitizer?" OFF) option(NB_TEST_SANITIZERS_UBSAN "Build tests with the address undefined behavior sanitizer?" OFF) option(NB_TEST_SANITIZERS_TSAN "Build tests with the thread sanitizer?" OFF) endif() ``` -------------------------------- ### Get object attribute Source: https://github.com/wjakob/nanobind/blob/master/docs/api_core.md Retrieves an attribute from an object. Raises python_error on failure unless a default value is provided. ```cpp object getattr(handle h, const char *key) ``` ```cpp object getattr(handle h, handle key) ``` ```cpp object getattr(handle h, const char *key, handle def) noexcept ``` ```cpp object getattr(handle h, handle key, handle def) noexcept ``` -------------------------------- ### Configure cibuildwheel in pyproject.toml Source: https://github.com/wjakob/nanobind/blob/master/docs/packaging.md Basic configuration for cibuildwheel including build verbosity and macOS deployment targets. ```toml [tool.cibuildwheel] # Necessary to see build output from the actual compilation build-verbosity = 1 # Optional: run pytest to ensure that the package was correctly built # test-command = "pytest {project}/tests" # test-requires = "pytest" # Needed for full C++17 support on macOS [tool.cibuildwheel.macos.environment] MACOSX_DEPLOYMENT_TARGET = "10.14" ``` -------------------------------- ### inst_take_ownership Source: https://github.com/wjakob/nanobind/blob/master/docs/api_core.md Creates an object that wraps an existing C++ instance and takes ownership. ```APIDOC ## inst_take_ownership(handle h, void *p) ### Description Creates an object of type `h` that wraps an existing C++ instance `p`. Both ready and destruct flags are set to true. ### Parameters - **h** (handle) - The type object created via class_. - **p** (void*) - The existing C++ instance to wrap. ``` -------------------------------- ### Adjust extension rpath settings Source: https://github.com/wjakob/nanobind/blob/master/docs/faq.md CMake commands to configure the build and install rpath for the extension to locate shared libraries. ```cmake set_property(TARGET my_ext APPEND PROPERTY BUILD_RPATH "$") set_property(TARGET my_ext APPEND PROPERTY INSTALL_RPATH ".. ?? ..") ``` -------------------------------- ### inst_mark_ready Source: https://github.com/wjakob/nanobind/blob/master/docs/api_core.md Sets the ready and destruct flags to true. ```APIDOC ## inst_mark_ready(handle h) ### Description Simultaneously set the ready and destruct flags of the instance `h` to true. ``` -------------------------------- ### Project Directory Structure Source: https://github.com/wjakob/nanobind/blob/master/docs/packaging.md The recommended layout for a nanobind project, separating C++ source and Python package files. ```text ├── README.md ├── CMakeLists.txt ├── pyproject.toml └── src/ ├── my_ext.cpp └── my_ext/ └── __init__.py ``` -------------------------------- ### Define base class with manual reference counting Source: https://github.com/wjakob/nanobind/blob/master/docs/ownership.md Example of a base class structure for manual intrusive reference counting. ```cpp class Object { ... private: mutable std::atomic m_ref_count { 0 }; PyObject *m_py_object = nullptr; }; ``` -------------------------------- ### nanobind_musl_static_libcpp Source: https://github.com/wjakob/nanobind/blob/master/docs/api_cmake.md Statically links libstdc++ and libgcc when targeting musllinux. ```APIDOC ## nanobind_musl_static_libcpp(target) ### Description Passes linker flags -static-libstdc++ and -static-libgcc when the environment indicates a musllinux build. ``` -------------------------------- ### Bind unique_ptr functions Source: https://github.com/wjakob/nanobind/blob/master/docs/ownership.md Example of binding C++ functions that create and consume Data instances via unique pointers. ```cpp #include namespace nb = nanobind; NB_MODULE(my_ext, m) { struct Data { }; nb::class_(m, "Data"); m.def("create", []() { return std::make_unique(); }); m.def("consume", [](std::unique_ptr x) { /* no-op */ }); } ``` -------------------------------- ### Interact with bound C++ class in Python Source: https://github.com/wjakob/nanobind/blob/master/docs/basics.md Example usage of the bound Dog class within an interactive Python session. ```pycon Python 3.11.1 (main, Dec 23 2022, 09:28:24) [Clang 14.0.0 (clang-1400.0.29.202)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import my_ext >>> d = my_ext.Dog('Max') >>> print(d) >>> d.name 'Max' >>> d.name = 'Charlie' >>> d.bark() 'Charlie: woof!' ``` -------------------------------- ### inst_zero Source: https://github.com/wjakob/nanobind/blob/master/docs/api_core.md Zero-initializes the contents of an instance. ```APIDOC ## inst_zero(handle h) ### Description Zero-initialize the contents of `h`. Sets the ready and destruct flags to true. ``` -------------------------------- ### Diagnose missing shared library errors Source: https://github.com/wjakob/nanobind/blob/master/docs/faq.md Example of an ImportError indicating that the nanobind shared library component cannot be located at runtime. ```pycon >>> import my_ext ImportError: dlopen(my_ext.cpython-311-darwin.so, 0x0002): Library not loaded: '@rpath/libnanobind.dylib' ``` -------------------------------- ### NB_TRAMPOLINE(base, size) Source: https://github.com/wjakob/nanobind/blob/master/docs/api_extra.md Installs a trampoline in an alias class to enable dispatching C++ virtual function calls to a Python implementation. ```APIDOC ## NB_TRAMPOLINE(base, size) ### Description Install a trampoline in an alias class to enable dispatching C++ virtual function calls to a Python implementation. ### Parameters - **base** - The base class type. - **size** - The size of the trampoline. ``` -------------------------------- ### Bind implicit conversion constructors Source: https://github.com/wjakob/nanobind/blob/master/docs/api_core.md Shows how to bind implicit conversion-capable constructors using nb::init_implicit or manual lower-level implementation. ```cpp nb::class_(m, "MyType") .def(nb::init_implicit()); ``` ```cpp nb::class_(m, "MyType") .def("__init__", [](MyType* t, const char* arg0) { new (t) MyType(arg0); }); nb::implicitly_convertible(); ``` -------------------------------- ### Verify Subclass Behavior in Python Source: https://github.com/wjakob/nanobind/blob/master/docs/classes.md Python usage demonstrating that instances expose methods from both base and derived classes. ```pycon >>> d = my_ext.Dog("Molly") >>> d.name 'Molly' >>> d.bark() 'Molly: woof!' ``` -------------------------------- ### Locate nanobind dependency Source: https://github.com/wjakob/nanobind/blob/master/docs/building.md Configures CMake to find nanobind based on whether it was installed via package managers or as a Git submodule. ```cmake # Detect the installed nanobind package and import it into CMake execute_process( COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE nanobind_ROOT) find_package(nanobind CONFIG REQUIRED) ``` ```cmake add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ext/nanobind) ``` -------------------------------- ### Define a C++ class with a factory method Source: https://github.com/wjakob/nanobind/blob/master/docs/classes.md Example of a C++ class that uses a static factory method instead of a public constructor. ```cpp class Pet { private: Pet(/* ... */); public: static std::unique_ptr make(std::string name, int age); void speak(); }; ```