Skip to main content

rootwin

There are a few ways of embedding C++ into python. All of them requires cling. Unlike what many people believe, there exist a working C++ implementation that is able to execute C++ code by interpreting it. Namely, cling. Moreover, there is a C++ library called root that accesses this interpreter programmatically. Additionally, root has python bindings which support C++17 but they only work on linux. Also, there is a seperate library called cppyy which works on windows if you manage to win the fight against its broken build system. By the way, it claims to support C++20 by default, but in practice it only supports C++14 and there is no way of increasing this revision. Lastly there is this library, rootwin, which works on windows and also supports C++17 and it's not fake. However, it's interoperability capabilities are more limited compared to root and cppyy. Specifically, C++ symbols you define are not automatically wrapped into python objects and made available to python. Nonetheless, you can use some techniques which are explained below to get some amount of interoperability.

Installation

pip install rootwin

Python Api

rootwin.ProcessLine(code)

Execute the given C++ code (or cling metacommand). code can be a bytes literal. code will be converted to ctypes.c_char_p since this is actually a dll function. Unlike what the name indicates, code can contain multiple lines. The only reason why this name is chose is to emphesize that this function does nothing but calls the upstream C++ root library's ProcessLine() function.

rootwin.root_interface

This is the underlying ctypes.CDLL instance. Currently, no functions other than ProcessLine() are exported since the need haven't arised.

C++ Api

This is the api available to the C++ code executed by rootwin.ProcessLine().

template<typename T>
T py_to_pointer(const char *name, bool local = true)

Convert a python int to a C++ pointer. name is expected to be the name of a python int. Expected scope of this int is determined by the local argument. If local is true, name is searched in the local variables of the currently executing python function. Otherwise, it is searched in python globals.

Passing C++ objects to python

Unlike cppyy and root libraries, manual work is needed to access C++ objects from python. High level steps are below:

  1. Prepare the python world for the next steps by instantiating a ctypes.c_longlong. This will be our "out" argument.
  2. Take the address of this variable and assign it to another variable
  3. Call rootwin.ProcessLine(code) where code is a 2 liner trick which exports the address of any C++ object to python.
  4. In the first line, call py_to_pointer<long long*>("p2") where "p2" is the name of the python variable we created in the step 2.
  5. Next, dereference the pointer returned by py_to_pointer and assign the address of the C++ object you want to access from python to it.
  6. ctypes.c_longlong we created in the first step will be updated by the operation we performed on step 5.
  7. Convert the ctypes data type to an ordinary python int by accessing its value attribute.
  8. Use pyptrs in order to dereference the final int.

Example:

import ctypes
import rootwin
import pyptrs

pointer = ctypes.c_longlong(0)
pointer2 = ctypes.addressof(pointer)
rootwin.ProcessLine(b"int cpp_var = 100;")
rootwin.ProcessLine(b"""long long *pointer2 = py_to_pointer<long long*>("pointer2");""")
rootwin.ProcessLine(b"""*pointer2 = reinterpret_cast<long long>(&cpp_var);""")
cpp_pointer = pyptrs.pointer_to_address(pointer.value, ctype = ctypes.c_int)
cpp_var = pyptrs.dereference(cpp_pointer)
var = cpp_var.value
print(var) # prints 100

This is a rather simple example but by applying the same logic, you can also transfer more complex objects to python. This is possible since pyptrs supports pointers to custom ctypes structures.

Another example:

import ctypes
import rootwin
import pyptrs

pointer = ctypes.c_longlong(0)
pointer2 = ctypes.addressof(pointer)
code = b"""
struct A
{
    int a = 10;
    int b = 20;
    int c = 30;
};

A cpp_object;
"""
rootwin.ProcessLine(code)
rootwin.ProcessLine(b"""long long *pointer2 = py_to_pointer<long long*>("pointer2");""")
rootwin.ProcessLine(b"""*pointer2 = reinterpret_cast<long long>(&cpp_object);""")
class A(ctypes.Structure):
    _fields_ = [("a", ctypes.c_int),
                ("b", ctypes.c_int),
                ("c", ctypes.c_int)]
    
cpp_pointer = pyptrs.pointer_to_address(pointer.value, ctype = A)
cpp_object = pyptrs.dereference(cpp_pointer)
b = cpp_object.b
print(b)

Metadata

Release files for rootwin 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rootwin 1.0.0
File Size Uploaded
rootwin-1.0.0.tar.gz 64.0 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for rootwin 1.0.0
File Interpreter ABI Platform
rootwin-1.0.0-py2.py3-none-any.whl Python 3, Python 2 none any Details

Total release size: 130.2 MB

Release files / rootwin-1.0.0.tar.gz

Download URL rootwin-1.0.0.tar.gz
Size 64.0 MB
Tags Source
SHA-256 checksum
How to use checksums
57d282de82cd034f69deb51f326aef191bf30cc7a85725f5357a92f70a981974
BLAKE2b-256 checksum
How to use checksums
fee1f7a106b2939b0ee5271ee9886025512ff014017fff87e53d9562ae215a66
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.0

Release files / rootwin-1.0.0-py2.py3-none-any.whl

Download URL rootwin-1.0.0-py2.py3-none-any.whl
Size 66.3 MB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
52b74838a9f891ff2ef40eda5e1a32f8aaf5419e619f2e5aa6a75d40b1205e51
BLAKE2b-256 checksum
How to use checksums
a9b0827c95656574eab0cb1409d3fba86eb1fd2f4721d689ee35cf2acff1a96a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.0

Release history Release notifications | RSS feed

1.1.3

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page