This projects implements Python bindings for C++ using C++26 reflection. The reflection provides meta information about entities(e.g. classes, functions, variables).
The main advantage of using reflection is that we can automatically build bindings without writing any additional code.
For example, there are C++ functions that we want to expose.
namespace test {
struct Age {
int age{};
Age(int age) : age{age} {}
int get_age(int value) { return age; }
void set_age(int value) { age = value; }
int add_to_age(int value) const { return age + value; }
};
int add(int a, int b) {
return a + b;
}
}All we need to do is to provide the test namespace:
REFLB_MODULE(example, test)By using reflection, the rebind can make entities(classes and functions) available for Python code. Exposing new methods does not require writing binding code.
import example
age = example.Age(10)
print("add to age", age.add_to_age(30))
print("get age", age.set_age(30))
print("sum 1 + 2", example.add(1, 2))The Dockerfile in the repo compiles trunk gcc and build the project.
- Build an image:
docker build -t rebind . - Run the image:
docker run -it --rm -v $(pwd):/rebind -t rebind - (Optional) if you want to run test, activate python via
source .venv/bin/activate - Build the project:
cmake -S . --build build&&cmake --build build
Prerequisites. By now, no mainstream compilers support reflection. a clang fork is an experimental implementation of the feature. It requires to build a clang compiler.
Build commands:
cmake -S llvm -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./install -DLLVM_ENABLE_PROJECTS='clang;lld' -DLLVM_ENABLE_RUNTIMES="libc;libunwind;libcxxabi;libcxx" && \
cmake --build build && \
cmake --install build
First, set up clang compilers for C++ and C:
export CC=/path_to_clang/install/bin/clang
export CXX=/path_to_clang/install/bin/clang++
Then, configure and build the project.
cmake -S . -B build -DCLANG_INSTALL_PREFIX=/path_to_clang/install -DUSE_STATIC_LIBCXX=ON && \
cmake --build build
These commands produce a shared library. To run a Python code, that library and python file should be in the same folder. Now we can run Python code, which invokes C++ functions.
Preparing step includes installing venv and install depencies.
python3 -m venv .venv
poetry install
Then running tests is simple:
cmake --build build --target pytest
Optional sanitizer builds:
cmake -S . -B build-asan -DENABLE_ADDRESS_SANITIZER=ON
cmake -S . -B build-ubsan -DENABLE_UNDEFINED_SANITIZER=ON
- No overload resolution
- Support =delete and other specifiers
- Support access to public member variables
- Handle types mismatch
- Handle exception translation (C++ → Python)
- Try replace std::array with std::inplace_vector
- Try to use concepts
- Use std::meta::parameters_of instead of function_trats struct.
- Use ranges as much as possible.
- And more