Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
91b4d21
use CppInterOp and Dispatch in cppyy-backend
aaronj0 Feb 10, 2026
120c170
[cppyy] Update CPyCppyy API to use InterOp based forks
aaronj0 Feb 10, 2026
6663c7d
minimal updates to cppyy frontend to make new cppyy work
aaronj0 Oct 27, 2025
631a0a6
[CPyCppyy] Update to latest
aaronj0 Feb 12, 2026
5fe8e0c
[cppyy-backend] Sync with compres forks, pass header location to clin…
aaronj0 Feb 12, 2026
d078e80
Don't use C++ 20 feature std::map::contains in CPPMethod
aaronj0 Feb 12, 2026
251f6ca
Don't use C++ 20 feature ends_with in CreateExecutor
aaronj0 Feb 12, 2026
70f050f
Expose CppGetProcAddress in libCling linker script
aaronj0 Feb 12, 2026
91f7be0
fix for gInterpreter and codegen for gInterpreter->Declare
aaronj0 Feb 13, 2026
100ab91
silence erroneous `__typeof__` declarations in Cppyy::GetType
aaronj0 Feb 13, 2026
635c3db
CPyCppyy: fix kUseStrict enum in CallContext
aaronj0 Feb 18, 2026
0a3e64b
[cppyy-backend] Syncup with upstream compres-forks
aaronj0 Mar 11, 2026
c422dba
[CPyCppyy] Fix more tests - Syncup with upstream (compres-forks)
aaronj0 Mar 11, 2026
a79415f
[windows] fix incompatible Py_ssize_t with vector<long int>
aaronj0 Mar 11, 2026
7b58ccd
[windows] drop dummy static that confused msvc
aaronj0 Mar 11, 2026
db98a50
Add missing Cling PushTransactionRAII for Lookups
aaronj0 Mar 12, 2026
ea9fd7b
[windows] Drop intptr_t usage and return Cpp::TCppIndex_t in EnumDat…
aaronj0 Mar 12, 2026
445da1d
[windows] undef `LoadLibrary` from windows.h before CppInterOp's Disp…
aaronj0 Mar 12, 2026
c5859fb
[backend] reconcile minor format diff with compres fork
aaronj0 Mar 13, 2026
8e90ad3
Add more RAII objects
aaronj0 Mar 27, 2026
042f601
revert changes in cppyy __init__
aaronj0 Mar 27, 2026
66eb416
[CPyCppyy] Sync up with compiler-research forks
aaronj0 Mar 28, 2026
59af7b3
drop extra RAII object
aaronj0 Mar 28, 2026
760a84a
[dispatch] disable verbose loadapi message unless debug
aaronj0 Mar 29, 2026
6c12723
[cppyy] Update test tags and revert changes in _cpython_cppyy
Vipul-Cariappa Mar 26, 2026
9c5a4b8
add gPad to ROOT facade
aaronj0 Mar 29, 2026
d3cdb55
revert changes that prevented import of support
aaronj0 Mar 30, 2026
1329ccd
upstream patch CppInterOp#880
aaronj0 Mar 30, 2026
66fbcd0
upstream patch cppyy-backend#192
aaronj0 Mar 30, 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
11 changes: 7 additions & 4 deletions bindings/pyroot/cppyy/CPyCppyy/include/CPyCppyy/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@
#endif
#include "Python.h"

#define CPYCPPYY_VERSION_HEX 0x010c10
#define CPYCPPYY_VERSION_HEX 0x011200

// Cppyy types
namespace Cppyy {
typedef size_t TCppScope_t;
typedef void* TCppScope_t;
typedef TCppScope_t TCppType_t;
typedef void* TCppEnum_t;
typedef void* TCppObject_t;
typedef intptr_t TCppMethod_t;
typedef void* TCppMethod_t;

typedef size_t TCppIndex_t;
typedef void* TCppFuncAddr_t;
Expand Down Expand Up @@ -124,6 +124,7 @@ class CPYCPPYY_CLASS_EXTERN Converter {

// create a converter based on its full type name and dimensions
CPYCPPYY_EXTERN Converter* CreateConverter(const std::string& name, cdims_t = 0);
CPYCPPYY_EXTERN Converter* CreateConverter(Cppyy::TCppType_t type, cdims_t = 0);

// delete a previously created converter
CPYCPPYY_EXTERN void DestroyConverter(Converter* p);
Expand Down Expand Up @@ -154,6 +155,7 @@ class CPYCPPYY_CLASS_EXTERN Executor {

// create an executor based on its full type name
CPYCPPYY_EXTERN Executor* CreateExecutor(const std::string& name, cdims_t = 0);
CPYCPPYY_EXTERN Executor* CreateExecutor(Cppyy::TCppType_t type, cdims_t = 0);

// delete a previously created executor
CPYCPPYY_EXTERN void DestroyConverter(Converter* p);
Expand Down Expand Up @@ -184,7 +186,8 @@ CPYCPPYY_EXTERN void* Instance_AsVoidPtr(PyObject* pyobject);
// void* to C++ Instance (python object proxy) conversion, returns a new reference
CPYCPPYY_EXTERN PyObject* Instance_FromVoidPtr(
void* addr, const std::string& classname, bool python_owns = false);

CPYCPPYY_EXTERN PyObject* Instance_FromVoidPtr(
void* addr, Cppyy::TCppScope_t klass_scope, bool python_owns = false);
// type verifiers for C++ Scope
CPYCPPYY_EXTERN bool Scope_Check(PyObject* pyobject);
CPYCPPYY_EXTERN bool Scope_CheckExact(PyObject* pyobject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,29 @@
#ifdef _MSC_VER
// Windows requires symbols to be explicitly exported
#define CPYCPPYY_EXPORT extern __declspec(dllexport)
#define CPYCPPYY_IMPORT extern __declspec(dllimport)
#define CPYCPPYY_CLASS_EXPORT __declspec(dllexport)

// CPYCPPYY_EXTERN is dual use in the public API
#ifndef CPYCPPYY_INTERNAL
#define CPYCPPYY_EXTERN extern __declspec(dllexport)
#define CPYCPPYY_CLASS_EXTERN __declspec(dllexport)
#else
#define CPYCPPYY_EXTERN extern
#define CPYCPPYY_CLASS_EXTERN
#define CPYCPPYY_EXTERN extern __declspec(dllimport)
#define CPYCPPYY_CLASS_EXTERN __declspec(dllimport)
#endif

#define CPYCPPYY_STATIC

#else
// Linux, Mac, etc.
#define CPYCPPYY_EXPORT extern
#define CPYCPPYY_IMPORT extern
#define CPYCPPYY_CLASS_EXPORT
#define CPYCPPYY_EXTERN extern
#define CPYCPPYY_CLASS_EXTERN
#define CPYCPPYY_STATIC static

#endif

#define CPYCPPYY_IMPORT extern

#endif // !CPYCPPYY_COMMONDEFS_H
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,16 @@

// Bindings
#include "CPyCppyy/CommonDefs.h"

#include <Python.h>

namespace CPyCppyy {
class PythonGILRAII {
PyGILState_STATE state;

public:
PythonGILRAII() : state(PyGILState_Ensure()) {}
~PythonGILRAII() { PyGILState_Release(state); }
};

class CPYCPPYY_CLASS_EXTERN DispatchPtr {
public:
Expand Down
40 changes: 40 additions & 0 deletions bindings/pyroot/cppyy/CPyCppyy/src/API.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "CPPInstance.h"
#include "CPPOverload.h"
#include "CPPScope.h"
#include "CPyCppyy/DispatchPtr.h"
#include "ProxyWrappers.h"
#include "PyStrings.h"

Expand Down Expand Up @@ -85,6 +86,7 @@ static bool Initialize()
}

if (!gMainDict) {
CPyCppyy::PythonGILRAII python_gil_raii;
// retrieve the main dictionary
gMainDict = PyModule_GetDict(
PyImport_AddModule(const_cast<char*>("__main__")));
Expand Down Expand Up @@ -121,6 +123,8 @@ void* CPyCppyy::Instance_AsVoidPtr(PyObject* pyobject)
if (!Initialize())
return nullptr;

PythonGILRAII python_gil_raii;

// check validity of cast
if (!CPPInstance_Check(pyobject))
return nullptr;
Expand All @@ -137,6 +141,8 @@ PyObject* CPyCppyy::Instance_FromVoidPtr(
if (!Initialize())
return nullptr;

PythonGILRAII python_gil_raii;

// perform cast (the call will check TClass and addr, and set python errors)
PyObject* pyobject = BindCppObjectNoCast(addr, Cppyy::GetScope(classname), false);

Expand All @@ -147,6 +153,25 @@ PyObject* CPyCppyy::Instance_FromVoidPtr(
return pyobject;
}

//-----------------------------------------------------------------------------
PyObject* CPyCppyy::Instance_FromVoidPtr(
void* addr, Cppyy::TCppScope_t klass_scope, bool python_owns)
{
// Bind the addr to a python object of class defined by classname.
if (!Initialize())
return nullptr;

PythonGILRAII python_gil_raii;

// perform cast (the call will check TClass and addr, and set python errors)
PyObject* pyobject = BindCppObjectNoCast(addr, klass_scope, false);

// give ownership, for ref-counting, to the python side, if so requested
if (python_owns && CPPInstance_Check(pyobject))
((CPPInstance*)pyobject)->PythonOwns();

return pyobject;
}
namespace CPyCppyy {
// version with C type arguments only for use with Numba
PyObject* Instance_FromVoidPtr(void* addr, const char* classname, int python_owns) {
Expand All @@ -161,6 +186,7 @@ bool CPyCppyy::Scope_Check(PyObject* pyobject)
if (!Initialize())
return false;

PythonGILRAII python_gil_raii;
return CPPScope_Check(pyobject);
}

Expand All @@ -171,6 +197,7 @@ bool CPyCppyy::Scope_CheckExact(PyObject* pyobject)
if (!Initialize())
return false;

PythonGILRAII python_gil_raii;
return CPPScope_CheckExact(pyobject);
}

Expand All @@ -181,6 +208,7 @@ bool CPyCppyy::Instance_Check(PyObject* pyobject)
if (!Initialize())
return false;

PythonGILRAII python_gil_raii;
// detailed walk through inheritance hierarchy
return CPPInstance_Check(pyobject);
}
Expand All @@ -192,13 +220,15 @@ bool CPyCppyy::Instance_CheckExact(PyObject* pyobject)
if (!Initialize())
return false;

PythonGILRAII python_gil_raii;
// direct pointer comparison of type member
return CPPInstance_CheckExact(pyobject);
}

//-----------------------------------------------------------------------------
bool CPyCppyy::Sequence_Check(PyObject* pyobject)
{
PythonGILRAII python_gil_raii;
// Extends on PySequence_Check() to determine whether an object can be iterated
// over (technically, all objects can b/c of C++ pointer arithmetic, hence this
// check isn't 100% accurate, but neither is PySequence_Check()).
Expand Down Expand Up @@ -232,6 +262,7 @@ bool CPyCppyy::Sequence_Check(PyObject* pyobject)
//-----------------------------------------------------------------------------
bool CPyCppyy::Instance_IsLively(PyObject* pyobject)
{
PythonGILRAII python_gil_raii;
// Test whether the given instance can safely return to C++
if (!CPPInstance_Check(pyobject))
return true; // simply don't know
Expand All @@ -251,6 +282,7 @@ bool CPyCppyy::Overload_Check(PyObject* pyobject)
if (!Initialize())
return false;

PythonGILRAII python_gil_raii;
// detailed walk through inheritance hierarchy
return CPPOverload_Check(pyobject);
}
Expand All @@ -262,6 +294,7 @@ bool CPyCppyy::Overload_CheckExact(PyObject* pyobject)
if (!Initialize())
return false;

PythonGILRAII python_gil_raii;
// direct pointer comparison of type member
return CPPOverload_CheckExact(pyobject);
}
Expand All @@ -279,6 +312,8 @@ bool CPyCppyy::Import(const std::string& mod_name)
if (!Initialize())
return false;

PythonGILRAII python_gil_raii;

PyObject* mod = PyImport_ImportModule(mod_name.c_str());
if (!mod) {
PyErr_Print();
Expand Down Expand Up @@ -342,6 +377,8 @@ void CPyCppyy::ExecScript(const std::string& name, const std::vector<std::string
if (!Initialize())
return;

PythonGILRAII python_gil_raii;

// verify arguments
if (name.empty()) {
std::cerr << "Error: no file name specified." << std::endl;
Expand Down Expand Up @@ -416,6 +453,7 @@ bool CPyCppyy::Exec(const std::string& cmd)
if (!Initialize())
return false;

PythonGILRAII python_gil_raii;
// execute the command
PyObject* result =
PyRun_String(const_cast<char*>(cmd.c_str()), Py_file_input, gMainDict, gMainDict);
Expand All @@ -441,6 +479,7 @@ const CPyCppyy::PyResult CPyCppyy::Eval(const std::string& expr)
if (!Initialize())
return PyResult();

PythonGILRAII python_gil_raii;
// evaluate the expression
PyObject* result =
PyRun_String(const_cast<char*>(expr.c_str()), Py_eval_input, gMainDict, gMainDict);
Expand Down Expand Up @@ -492,6 +531,7 @@ void CPyCppyy::Prompt() {
if (!Initialize())
return;

PythonGILRAII python_gil_raii;
// enter i/o interactive mode
PyRun_InteractiveLoop(stdin, const_cast<char*>("\0"));
}
2 changes: 1 addition & 1 deletion bindings/pyroot/cppyy/CPyCppyy/src/CPPClassMethod.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ PyObject* CPyCppyy::CPPClassMethod::Call(CPPInstance*&
if ((!self || (PyObject*)self == Py_None) && nargs) {
PyObject* arg0 = CPyCppyy_PyArgs_GET_ITEM(args, 0);
if (CPPInstance_Check(arg0) && fArgsRequired <= nargs - 1 &&
Cppyy::IsSubtype(reinterpret_cast<CPPInstance *>(arg0)->ObjectIsA(), GetScope())) {
Cppyy::IsSubclass(reinterpret_cast<CPPInstance *>(arg0)->ObjectIsA(), GetScope())) {
args += 1; // drops first argument
nargsf -= 1;
}
Expand Down
19 changes: 11 additions & 8 deletions bindings/pyroot/cppyy/CPyCppyy/src/CPPConstructor.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
//- data _____________________________________________________________________
namespace CPyCppyy {
extern PyObject* gNullPtrObject;
void* Instance_AsVoidPtr(PyObject* pyobject);
PyObject* Instance_FromVoidPtr(void* addr, Cppyy::TCppScope_t klass_scope, bool python_owns);
}


Expand Down Expand Up @@ -44,7 +46,7 @@ PyObject* CPyCppyy::CPPConstructor::Reflex(
if (request == Cppyy::Reflex::RETURN_TYPE) {
std::string fn = Cppyy::GetScopedFinalName(this->GetScope());
if (format == Cppyy::Reflex::OPTIMAL || format == Cppyy::Reflex::AS_TYPE)
return CreateScopeProxy(fn);
return CreateScopeProxy(this->GetScope());
else if (format == Cppyy::Reflex::AS_STRING)
return CPyCppyy_PyText_FromString(fn.c_str());
}
Expand All @@ -56,7 +58,6 @@ PyObject* CPyCppyy::CPPConstructor::Reflex(
PyObject* CPyCppyy::CPPConstructor::Call(CPPInstance*& self,
CPyCppyy_PyArgs_t args, size_t nargsf, PyObject* kwds, CallContext* ctxt)
{

// setup as necessary
if (fArgsRequired == -1 && !this->Initialize(ctxt))
return nullptr; // important: 0, not Py_None
Expand All @@ -81,11 +82,12 @@ PyObject* CPyCppyy::CPPConstructor::Call(CPPInstance*& self,
const auto cppScopeFlags = ((CPPScope*)Py_TYPE(self))->fFlags;

// Do nothing if the constructor is explicit and we are in an implicit
// conversion context. We recognize this by checking the CPPScope::kNoImplicit
// flag, as further implicit conversions are disabled to prevent infinite
// recursion. See also the ConvertImplicit() helper in Converters.cxx.
if((cppScopeFlags & CPPScope::kNoImplicit) && Cppyy::IsExplicit(GetMethod()))
return nullptr;
// conversion context. See also the ConvertImplicit() helper in Converters.cxx.
if((cppScopeFlags & CPPScope::kActiveImplicitCall) && Cppyy::IsExplicit(GetMethod())) {
// FIXME: Cases with explicit marked std::complex constructors where we expect implicit conversionss
if (Cppyy::GetMethodSignature(GetMethod(), true).find("std::complex") == std::string::npos)
return nullptr;
}

// self provides the python context for lifelines
if (!ctxt->fPyContext)
Expand Down Expand Up @@ -135,7 +137,7 @@ PyObject* CPyCppyy::CPPConstructor::Call(CPPInstance*& self,

} else {
// translate the arguments
if (cppScopeFlags & CPPScope::kNoImplicit)
if (cppScopeFlags & CPPScope::kActiveImplicitCall)
ctxt->fFlags |= CallContext::kNoImplicit;
if (!this->ConvertAndSetArgs(cargs.fArgs, cargs.fNArgsf, ctxt))
return nullptr;
Expand Down Expand Up @@ -182,6 +184,7 @@ PyObject* CPyCppyy::CPPConstructor::Call(CPPInstance*& self,
return nullptr;
}


//----------------------------------------------------------------------------
CPyCppyy::CPPMultiConstructor::CPPMultiConstructor(Cppyy::TCppScope_t scope, Cppyy::TCppMethod_t method) :
CPPConstructor(scope, method)
Expand Down
Loading
Loading