Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
2cdcc73
[cppinterop] Add `IsPackExpansionType`, `IsOperator` and `IsConversio…
Vipul-Cariappa Oct 13, 2026
ec249a7
[cppinterop] Rework `BestOverloadFunctionMatch` for methods, operator…
Vipul-Cariappa Oct 13, 2026
7831d60
[cppinterop] Refactor according to code review
Vipul-Cariappa Oct 14, 2026
3890823
[cppjit] [cpyrt] Generate the PyStrings cache from a single X-macro l…
guitargeek Oct 7, 2026
56e184f
[cppjit] [cpyrt] Remove RegisterConverterAlias() and RegisterExecutor…
guitargeek Oct 9, 2026
0b24f98
[cppjit] Check for smart pointers by class instead of by name (compil…
guitargeek Oct 9, 2026
a41f663
[cppjit] [cpyrt] Fix leaked container reference in vector_iter (compi…
guitargeek Oct 9, 2026
7158e0b
[cppjit] Adopt Clang-driven overload resolution from CppInterOp
Vipul-Cariappa Aug 27, 2026
db4e494
[cppjit] Fix crashes and overload regressions on new overload resolution
aaronj0 Sep 2, 2026
d45e4a1
[cppjit] Update tests for new overload resolution behaviour
aaronj0 Sep 2, 2026
4fadd28
[cppjit] minor refactors
Vipul-Cariappa Oct 13, 2026
b69c600
[cppjit] Implement `IsEquivalentTypes` to check if two types are equi…
Vipul-Cariappa Oct 13, 2026
6c0cdfa
[cppjit] `BestOverloadFunctionMatch` loop optimization
Vipul-Cariappa Oct 13, 2026
edfff1c
[cppjit] fix cases where `ambiguous_candidates` have duplicate entries
Vipul-Cariappa Oct 13, 2026
c53429c
[cppjit] Remove dead code
Vipul-Cariappa Oct 13, 2026
d508a1a
[cppjit] fix compiler-research/cppjit#151
Vipul-Cariappa Oct 14, 2026
142dbc5
[cppinterop] Pass ambiguous_candidates in the TemplatedOperatorArrow …
Vipul-Cariappa Oct 14, 2026
2352dea
[cppjit] Match the selected overload by canonical declaration
Vipul-Cariappa Oct 16, 2026
42d2c34
[cppjit] Use the C++ element type name of low-level views in overloads
Vipul-Cariappa Oct 16, 2026
83ea4bc
[cppjit] Spell ctypes arguments as their C types in overload prototypes
Vipul-Cariappa Oct 16, 2026
37f5201
[cppjit] Spell the object of a call through a smart pointer as the po…
Vipul-Cariappa Oct 16, 2026
650bbe4
[cppjit] Spell numpy scalars and arrays as their C types in overload …
Vipul-Cariappa Oct 16, 2026
9c31ea1
[cppjit] Derive OverloadResolutionException from TypeError
Vipul-Cariappa Oct 16, 2026
8f2427f
[cppjit] Spell an empty list argument as an initializer_list
Vipul-Cariappa Oct 16, 2026
f76470a
[cppjit] Resolve __overload__ of templated method sets with the object
Vipul-Cariappa Oct 16, 2026
45b1427
[cppjit] Bind an object of another class to T&& through a temporary
Vipul-Cariappa Oct 16, 2026
3ea3622
[cppjit] Return enum instances for data members of enum type
Vipul-Cariappa Oct 16, 2026
245e802
[cppjit] Raise OverloadResolutionException when no template overload …
Vipul-Cariappa Oct 16, 2026
eef8450
[cppjit] Don't leave an error set when a vector iterator has no data …
Vipul-Cariappa Oct 16, 2026
cd61cbb
[cppjit] Fail GetMethodTemplate if the argument types can't be resolved
Vipul-Cariappa Oct 16, 2026
d829d6a
[cppjit] Match keyword arguments to parameters by name in overload re…
Vipul-Cariappa Oct 16, 2026
b1f43d7
[cppjit] Honour the silent flag of interop::Compile again
Vipul-Cariappa Oct 16, 2026
1434944
[cppjit] Update tests tags
Vipul-Cariappa Oct 20, 2026
5f31785
[cppjit] Spell a pointer proxy as an lvalue when it is the object of …
Vipul-Cariappa Oct 21, 2026
123f446
[cppjit] Spell the object of unbound templated method calls as an object
Vipul-Cariappa Oct 21, 2026
a3035ad
[cppjit] Don't mix static and non-static methods called on an object
Vipul-Cariappa Oct 21, 2026
548aff3
[cppjit] Pass the object as the class declaring the candidate methods
Vipul-Cariappa Oct 21, 2026
0837038
[RF][PyROOT] Construct RooArgList/RooArgSet from Python lists and tuples
Vipul-Cariappa Oct 16, 2026
9e4505c
[RF][PyROOT] Convert lists of RooFit objects in keyword-argument pyth…
Vipul-Cariappa Oct 16, 2026
56bf82e
[RF][PyROOT] Pick RooFit::Components(const char*) for Python strings
Vipul-Cariappa Oct 16, 2026
df889dc
[PyROOT] Allow constructing std::vector and RVec from numpy arrays
Vipul-Cariappa Oct 16, 2026
2bd0a75
[PyROOT] Pass the object address as void* in TClass.DynamicCast()
Vipul-Cariappa Oct 16, 2026
30fa7b9
[PyROOT] Pass the dispatcher address as void* receiver in TQObject.Co…
Vipul-Cariappa Oct 16, 2026
42a6c03
[PyROOT] Annotate Python callables passed to the TF1, TF2 and TF3 con…
Vipul-Cariappa Oct 16, 2026
61d9276
[PyROOT] Expect std::invalid_argument for an empty RDataFrame file list
Vipul-Cariappa Oct 16, 2026
c3c7385
[PyROOT] Accept iterators as RDataFrame constructor arguments
Vipul-Cariappa Oct 16, 2026
5b2f21b
[PyROOT] Convert a list of result pointers for RDF.RunGraphs()
Vipul-Cariappa Oct 16, 2026
49ae252
[PyROOT] Fill RCsvDS column types element-wise in MakeCSVDataFrame()
Vipul-Cariappa Oct 16, 2026
ccbe2de
[PyROOT] Pass the object address as void* in TDirectory.WriteObject()
Vipul-Cariappa Oct 16, 2026
55a8ba0
[PyROOT] Call the void* overload explicitly in TTree.SetBranchAddress()
Vipul-Cariappa Oct 16, 2026
21c99e2
[PyROOT] Select TTree::Branch(const char*, Int_t, Int_t) explicitly
Vipul-Cariappa Oct 16, 2026
eb4bb94
[PyROOT] Pass an explicit T** to BranchPtrToPtr for proxies owning th…
Vipul-Cariappa Oct 16, 2026
314f0b5
[RF][PyROOT] Convert lists of RooFit objects in all RooFit constructors
Vipul-Cariappa Oct 16, 2026
7b6deb0
[RF][PyROOT] Convert lists of RooFit objects in tuple keyword arguments
Vipul-Cariappa Oct 16, 2026
c9d25d9
[PyROOT] Support TLegend.AddEntry(0, label) for entries without an ob…
Vipul-Cariappa Oct 16, 2026
842c51b
[df] Expect std::invalid_argument when merging different RDF results
Vipul-Cariappa Oct 16, 2026
29f3bc6
[PyROOT][roottest] Expect an error for a call that is ambiguous in C++
Vipul-Cariappa Oct 16, 2026
9e76a60
[PyROOT] Select TColor::GetColor(Float_t, ...) for float components
Vipul-Cariappa Oct 16, 2026
ab081c1
[df][PyROOT] Pass column lists as std::vector in the Define/Filter py…
Vipul-Cariappa Oct 16, 2026
59ed930
[df][tutorials] Don't pass the number of parameters for TF1 formulas …
Vipul-Cariappa Oct 16, 2026
b169a62
[RF][PyROOT] Import a list of objects into a RooWorkspace as a RooArgSet
Vipul-Cariappa Oct 16, 2026
54335a5
[PyROOT] Allow constructing RVec (and std::vector) from an iterator
Vipul-Cariappa Oct 16, 2026
917d20d
[hist][PyROOT] Pythonize RHist and RHistEngine construction from Pyth…
Vipul-Cariappa Oct 16, 2026
db9e6e8
[math][tutorials] Pass nullptr for the initial parameters in combined…
Vipul-Cariappa Oct 16, 2026
d0126de
[df][DistRDF] Merge the RMergeableValues, not the unique_ptrs holding…
Vipul-Cariappa Oct 16, 2026
ff6315f
[RF][PyROOT] Convert lists of RooFit objects in table(), get() and Mo…
Vipul-Cariappa Oct 16, 2026
b042b9f
[PyROOT] Select the const char* overloads of TText for Python strings
Vipul-Cariappa Oct 16, 2026
2cdf7bb
[PyROOT][roottest] Select the make_any<T*> instantiation taking a T* …
Vipul-Cariappa Oct 16, 2026
56a298e
[df][PyROOT] Construct HistoND/HistoNSparseD models from tuples like …
Vipul-Cariappa Oct 16, 2026
d363401
[ntuple][PyROOT] Pass the entry itself to RNTupleWriter.Fill and Load…
Vipul-Cariappa Oct 21, 2026
297d7a4
[PyROOT] Append Python buffers to std::vector with += in a pythonization
Vipul-Cariappa Oct 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion bindings/distrdf/python/DistRDF/Backends/Utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,17 @@ def merge_values(mergeable_out, mergeable_in):
Generally the arguments are `RMergeableValue` instances that can be directly
passed to the C++ function responsible for merging them.
"""
ROOT.Detail.RDF.MergeValues(mergeable_out, mergeable_in)
# The mergeables are usually held by std::unique_ptrs: pass the objects
# themselves, as passing the smart pointers would select the MergeValues
# overload that takes (and thus moves) them by value.
ROOT.Detail.RDF.MergeValues(_pointee(mergeable_out), _pointee(mergeable_in))


def _pointee(obj):
"""Return the object a smart pointer proxy points to, or the object itself."""
smartptr = getattr(obj, "__smartptr__", None)
smartptr = smartptr() if smartptr is not None else None
return smartptr.get() if smartptr else obj


@merge_values.register(AsNumpyResult)
Expand Down
2 changes: 2 additions & 0 deletions bindings/pyroot/cppjit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ include(GNUInstallDirs)
# This option won't make a lot of sense since we only ship the shared library in site-packages
# Perhaps this should permanently be OFF and users can build their own CppInterOp if they want to run the tests?
option(CPPJIT_ENABLE_CPPINTEROP_TESTS "enable CppInterOp tests" OFF)
# Temporary pin to the overload-resolution development branch so CI builds
# and tests it. Returns to a pinned commit once that branch lands.
set(CPPINTEROP_GIT_REPOSITORY "https://github.com/compiler-research/CppInterOp.git" CACHE STRING "")
set(CPPINTEROP_GIT_TAG "c8126249dd18363000b89333b34313ca2a83fb82" CACHE STRING "")
set(CPPINTEROP_SOURCE_DIR "" CACHE PATH
Expand Down
4 changes: 4 additions & 0 deletions bindings/pyroot/cppjit/python/cppjit/_cpython_cppjit.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
"_end_capture_stderr",
"_lock_interpreter",
"_unlock_interpreter",
"OverloadResolutionException",
"OverloadAmbiguityException",
]


Expand Down Expand Up @@ -207,6 +209,8 @@ def _add_default_paths():
bind_object = _backend.bind_object
nullptr = _backend.nullptr
default = _backend.default
OverloadResolutionException = _backend.OverloadResolutionException
OverloadAmbiguityException = _backend.OverloadAmbiguityException


def load_reflection_info(name):
Expand Down
8 changes: 0 additions & 8 deletions bindings/pyroot/cppjit/src/cpyrt/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,6 @@ typedef Converter* (*ConverterFactory_t)(cdims_t);
CPYRT_EXTERN bool RegisterConverter(const std::string& name,
ConverterFactory_t);

// register a custom converter that is a reference to an existing converter
CPYRT_EXTERN bool RegisterConverterAlias(const std::string& name,
const std::string& target);

// remove a custom converter
CPYRT_EXTERN bool UnregisterConverter(const std::string& name);

Expand Down Expand Up @@ -176,10 +172,6 @@ CPYRT_EXTERN void DestroyConverter(Converter* p);
typedef Executor* (*ExecutorFactory_t)(cdims_t);
CPYRT_EXTERN bool RegisterExecutor(const std::string& name, ExecutorFactory_t);

// register a custom executor that is a reference to an existing converter
CPYRT_EXTERN bool RegisterExecutorAlias(const std::string& name,
const std::string& target);

// remove a custom executor
CPYRT_EXTERN bool UnregisterExecutor(const std::string& name);

Expand Down
14 changes: 1 addition & 13 deletions bindings/pyroot/cppjit/src/cpyrt/CPPDataMember.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,7 @@ void cpyrt::CPPDataMember::Set(interop::TCppScope_t scope,
type = interop::GetDatamemberType(fScope);
fFullType = interop::GetTypeAsString(type);

// Get the integer type if it's an enum
if (interop::IsEnumType(type))
if (interop::IsEnumType(type) && fFullType == "std::byte")
type = interop::ResolveType(type);

if (interop::IsConstVar(fScope))
Expand All @@ -382,17 +381,6 @@ void cpyrt::CPPDataMember::Set(interop::TCppScope_t scope,
fDescription = PyUnicode_FromString(name.c_str());
}

//-----------------------------------------------------------------------------
void cpyrt::CPPDataMember::Set(interop::TCppScope_t scope,
const std::string& name, void* address) {
fEnclosingScope = scope;
fDescription = PyUnicode_FromString(name.c_str());
fOffset = (intptr_t)address;
fFlags = kIsStaticData | kIsConstData;
fConverter = CreateConverter("internal_enum_type_t");
fFullType = "unsigned int";
}

//-----------------------------------------------------------------------------
void* cpyrt::CPPDataMember::GetAddress(CPPInstance* pyobj) {
// class attributes, global properties
Expand Down
11 changes: 0 additions & 11 deletions bindings/pyroot/cppjit/src/cpyrt/CPPDataMember.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class CPPInstance;
class CPPDataMember {
public:
void Set(interop::TCppScope_t scope, interop::TCppScope_t var);
void Set(interop::TCppScope_t scope, const std::string& name, void* address);

std::string GetName();
void* GetAddress(CPPInstance* pyobj /* owner */);
Expand Down Expand Up @@ -57,16 +56,6 @@ inline CPPDataMember* CPPDataMember_New(interop::TCppScope_t scope,
return pyprop;
}

inline CPPDataMember* CPPDataMember_NewConstant(interop::TCppScope_t scope,
const std::string& name,
void* address) {
// Create an initialize a new property descriptor, given the C++ datum.
CPPDataMember* pyprop = (CPPDataMember*)CPPDataMember_Type.tp_new(
&CPPDataMember_Type, nullptr, nullptr);
pyprop->Set(scope, name, address);
return pyprop;
}

} // namespace cppjit::cpyrt

#endif // !CPYRT_CPPDATAMEMBER_H
3 changes: 3 additions & 0 deletions bindings/pyroot/cppjit/src/cpyrt/CPPExcInstance.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#ifndef CPYRT_CPPEXCINSTANCE_H
#define CPYRT_CPPEXCINSTANCE_H

#include "Python.h"
#include "cpyrt/CommonDefs.h"

//////////////////////////////////////////////////////////////////////////////
// //
// cppjit::cpyrt::CPPExceptionInstance //
Expand Down
54 changes: 6 additions & 48 deletions bindings/pyroot/cppjit/src/cpyrt/CPPInstance.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -42,51 +42,6 @@ extern PyObject* gNullPtrObject;
// pointer to the smart pointer. They carry a pointer to the Python-sode smart
// class for dereferencing to get to the actual instance pointer.

//- private helpers ----------------------------------------------------------
namespace {

// Several specific use cases require extra data in a CPPInstance, but can not
// be a new type. E.g. cross-inheritance derived types are by definition added
// a posterio, and caching of datamembers is up to the datamember, not the
// instance type. To not have normal use of CPPInstance take extra memory, this
// extended data can slot in place of fObject for those use cases.

struct ExtendedData {
ExtendedData()
: fObject(nullptr), fSmartClass(nullptr), fDispatchPtr(nullptr),
fArraySize(0) {}
~ExtendedData() {
for (auto& pc : fDatamemberCache)
Py_XDECREF(pc.second);
fDatamemberCache.clear();
}

// the original object reference it replaces (Note: has to be first data
// member, see usage in GetObjectRaw(), e.g. for ptr-ptr passing)
void* fObject;

// for caching expensive-to-create data member representations
cpyrt::CI_DatamemberCache_t fDatamemberCache;

// for smart pointer types
cpyrt::CPPSmartClass* fSmartClass;

// for back-referencing from Python-derived instances
cpyrt::DispatchPtr* fDispatchPtr;

// for representing T* as a low-level array
Py_ssize_t fArraySize;
};

} // unnamed namespace

#define EXT_OBJECT(pyobj) ((ExtendedData*)((pyobj)->fObject))->fObject
#define DATA_CACHE(pyobj) ((ExtendedData*)((pyobj)->fObject))->fDatamemberCache
#define SMART_CLS(pyobj) ((ExtendedData*)((pyobj)->fObject))->fSmartClass
#define SMART_TYPE(pyobj) SMART_CLS(pyobj)->fCppType
#define DISPATCHPTR(pyobj) ((ExtendedData*)((pyobj)->fObject))->fDispatchPtr
#define ARRAY_SIZE(pyobj) ((ExtendedData*)((pyobj)->fObject))->fArraySize

inline void cpyrt::CPPInstance::CreateExtension() {
if (fFlags & kIsExtended)
return;
Expand Down Expand Up @@ -549,7 +504,8 @@ static inline PyObject* eqneq_binop(CPPClass* klass, PyObject* self,
const char* cppop = op == Py_EQ ? "==" : "!=";
PyCallable* pyfunc = FindBinaryOperator(self, obj, cppop);
if (pyfunc)
binop = (PyObject*)CPPOverload_New(cppop, pyfunc);
binop = (PyObject*)CPPOverload_New(
cppop, interop::GetParentScope(pyfunc->GetMethod().data), pyfunc);
else {
Py_INCREF(Py_None);
binop = Py_None;
Expand Down Expand Up @@ -613,7 +569,8 @@ static inline void* cast_actual(void* obj) {
PyCallable* pyfunc = \
Utility::FindBinaryOperator((PyObject*)self, other, #op); \
if (pyfunc) \
ometh = (PyObject*)CPPOverload_New(#label, pyfunc); \
ometh = (PyObject*)CPPOverload_New( \
#label, interop::GetParentScope(pyfunc->GetMethod().data), pyfunc); \
} \
meth = ometh;

Expand Down Expand Up @@ -1005,7 +962,8 @@ static PyGetSetDef op_getset[] = {
PyErr_Clear(); \
PyCallable* pyfunc = Utility::FindBinaryOperator(left, right, #op); \
if (pyfunc) \
meth = (PyObject*)CPPOverload_New(#name, pyfunc); \
meth = (PyObject*)CPPOverload_New( \
#name, interop::GetParentScope(pyfunc->GetMethod().data), pyfunc); \
else { \
PyErr_SetString(PyExc_NotImplementedError, ""); \
return nullptr; \
Expand Down
47 changes: 47 additions & 0 deletions bindings/pyroot/cppjit/src/cpyrt/CPPInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "CommonDefs.h"
#include "cppjit_interop.h"

#include "cpyrt/DispatchPtr.h"

// Standard
#include <utility>
#include <vector>
Expand Down Expand Up @@ -146,4 +148,49 @@ void op_dealloc_nofree(CPPInstance*);

} // namespace cppjit::cpyrt

//- private helpers ----------------------------------------------------------
namespace {

// Several specific use cases require extra data in a CPPInstance, but can not
// be a new type. E.g. cross-inheritance derived types are by definition added
// a posterio, and caching of datamembers is up to the datamember, not the
// instance type. To not have normal use of CPPInstance take extra memory, this
// extended data can slot in place of fObject for those use cases.

struct ExtendedData {
ExtendedData()
: fObject(nullptr), fSmartClass(nullptr), fDispatchPtr(nullptr),
fArraySize(0) {}
~ExtendedData() {
for (auto& pc : fDatamemberCache)
Py_XDECREF(pc.second);
fDatamemberCache.clear();
}

// the original object reference it replaces (Note: has to be first data
// member, see usage in GetObjectRaw(), e.g. for ptr-ptr passing)
void* fObject;

// for caching expensive-to-create data member representations
cppjit::cpyrt::CI_DatamemberCache_t fDatamemberCache;

// for smart pointer types
cppjit::cpyrt::CPPSmartClass* fSmartClass;

// for back-referencing from Python-derived instances
cppjit::cpyrt::DispatchPtr* fDispatchPtr;

// for representing T* as a low-level array
Py_ssize_t fArraySize;
};

} // unnamed namespace

#define EXT_OBJECT(pyobj) ((ExtendedData*)((pyobj)->fObject))->fObject
#define DATA_CACHE(pyobj) ((ExtendedData*)((pyobj)->fObject))->fDatamemberCache
#define SMART_CLS(pyobj) ((ExtendedData*)((pyobj)->fObject))->fSmartClass
#define SMART_TYPE(pyobj) SMART_CLS(pyobj)->fCppType
#define DISPATCHPTR(pyobj) ((ExtendedData*)((pyobj)->fObject))->fDispatchPtr
#define ARRAY_SIZE(pyobj) ((ExtendedData*)((pyobj)->fObject))->fArraySize

#endif // !CPYRT_CPPINSTANCE_H
Loading
Loading