Skip to content

Commit 0d5a63c

Browse files
committed
[cppyy] Update CPyCppyy API to use InterOp based forks
1 parent c1c120d commit 0d5a63c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1751
-1311
lines changed

bindings/pyroot/cppyy/CPyCppyy/include/CPyCppyy/API.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@
2525
#endif
2626
#include "Python.h"
2727

28-
#define CPYCPPYY_VERSION_HEX 0x010c10
28+
#define CPYCPPYY_VERSION_HEX 0x011200
2929

3030
// Cppyy types
3131
namespace Cppyy {
32-
typedef size_t TCppScope_t;
32+
typedef void* TCppScope_t;
3333
typedef TCppScope_t TCppType_t;
3434
typedef void* TCppEnum_t;
3535
typedef void* TCppObject_t;
36-
typedef intptr_t TCppMethod_t;
36+
typedef void* TCppMethod_t;
3737

3838
typedef size_t TCppIndex_t;
3939
typedef void* TCppFuncAddr_t;
@@ -124,6 +124,7 @@ class CPYCPPYY_CLASS_EXTERN Converter {
124124

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

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

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

158160
// delete a previously created executor
159161
CPYCPPYY_EXTERN void DestroyConverter(Converter* p);
@@ -180,7 +182,8 @@ CPYCPPYY_EXTERN void* Instance_AsVoidPtr(PyObject* pyobject);
180182
// void* to C++ Instance (python object proxy) conversion, returns a new reference
181183
CPYCPPYY_EXTERN PyObject* Instance_FromVoidPtr(
182184
void* addr, const std::string& classname, bool python_owns = false);
183-
185+
CPYCPPYY_EXTERN PyObject* Instance_FromVoidPtr(
186+
void* addr, Cppyy::TCppScope_t klass_scope, bool python_owns = false);
184187
// type verifiers for C++ Scope
185188
CPYCPPYY_EXTERN bool Scope_Check(PyObject* pyobject);
186189
CPYCPPYY_EXTERN bool Scope_CheckExact(PyObject* pyobject);

bindings/pyroot/cppyy/CPyCppyy/include/CPyCppyy/CommonDefs.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,29 @@
66
#ifdef _MSC_VER
77
// Windows requires symbols to be explicitly exported
88
#define CPYCPPYY_EXPORT extern __declspec(dllexport)
9+
#define CPYCPPYY_IMPORT extern __declspec(dllimport)
910
#define CPYCPPYY_CLASS_EXPORT __declspec(dllexport)
1011

1112
// CPYCPPYY_EXTERN is dual use in the public API
1213
#ifndef CPYCPPYY_INTERNAL
1314
#define CPYCPPYY_EXTERN extern __declspec(dllexport)
1415
#define CPYCPPYY_CLASS_EXTERN __declspec(dllexport)
1516
#else
16-
#define CPYCPPYY_EXTERN extern
17-
#define CPYCPPYY_CLASS_EXTERN
17+
#define CPYCPPYY_EXTERN extern __declspec(dllimport)
18+
#define CPYCPPYY_CLASS_EXTERN __declspec(dllimport)
1819
#endif
1920

2021
#define CPYCPPYY_STATIC
2122

2223
#else
2324
// Linux, Mac, etc.
2425
#define CPYCPPYY_EXPORT extern
26+
#define CPYCPPYY_IMPORT extern
2527
#define CPYCPPYY_CLASS_EXPORT
2628
#define CPYCPPYY_EXTERN extern
2729
#define CPYCPPYY_CLASS_EXTERN
2830
#define CPYCPPYY_STATIC static
2931

3032
#endif
3133

32-
#define CPYCPPYY_IMPORT extern
33-
3434
#endif // !CPYCPPYY_COMMONDEFS_H

bindings/pyroot/cppyy/CPyCppyy/src/API.cxx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,23 @@ PyObject* CPyCppyy::Instance_FromVoidPtr(
135135
return pyobject;
136136
}
137137

138+
//-----------------------------------------------------------------------------
139+
PyObject* CPyCppyy::Instance_FromVoidPtr(
140+
void* addr, Cppyy::TCppScope_t klass_scope, bool python_owns)
141+
{
142+
// Bind the addr to a python object of class defined by classname.
143+
if (!Initialize())
144+
return nullptr;
145+
146+
// perform cast (the call will check TClass and addr, and set python errors)
147+
PyObject* pyobject = BindCppObjectNoCast(addr, klass_scope, false);
148+
149+
// give ownership, for ref-counting, to the python side, if so requested
150+
if (python_owns && CPPInstance_Check(pyobject))
151+
((CPPInstance*)pyobject)->PythonOwns();
152+
153+
return pyobject;
154+
}
138155
namespace CPyCppyy {
139156
// version with C type arguments only for use with Numba
140157
PyObject* Instance_FromVoidPtr(void* addr, const char* classname, int python_owns) {
@@ -226,7 +243,7 @@ bool CPyCppyy::Instance_IsLively(PyObject* pyobject)
226243

227244
// the instance fails the lively test if it owns the C++ object while having a
228245
// reference count of 1 (meaning: it could delete the C++ instance any moment)
229-
if (Py_REFCNT(pyobject) <= 1 && (((CPPInstance*)pyobject)->fFlags & CPPInstance::kIsOwner))
246+
if (pyobject->ob_refcnt <= 1 && (((CPPInstance*)pyobject)->fFlags & CPPInstance::kIsOwner))
230247
return false;
231248

232249
return true;

bindings/pyroot/cppyy/CPyCppyy/src/CPPConstructor.cxx

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
//- data _____________________________________________________________________
1616
namespace CPyCppyy {
1717
extern PyObject* gNullPtrObject;
18+
void* Instance_AsVoidPtr(PyObject* pyobject);
19+
PyObject* Instance_FromVoidPtr(void* addr, Cppyy::TCppScope_t klass_scope, bool python_owns);
1820
}
1921

2022

@@ -44,7 +46,7 @@ PyObject* CPyCppyy::CPPConstructor::Reflex(
4446
if (request == Cppyy::Reflex::RETURN_TYPE) {
4547
std::string fn = Cppyy::GetScopedFinalName(this->GetScope());
4648
if (format == Cppyy::Reflex::OPTIMAL || format == Cppyy::Reflex::AS_TYPE)
47-
return CreateScopeProxy(fn);
49+
return CreateScopeProxy(this->GetScope());
4850
else if (format == Cppyy::Reflex::AS_STRING)
4951
return CPyCppyy_PyText_FromString(fn.c_str());
5052
}
@@ -56,7 +58,6 @@ PyObject* CPyCppyy::CPPConstructor::Reflex(
5658
PyObject* CPyCppyy::CPPConstructor::Call(CPPInstance*& self,
5759
CPyCppyy_PyArgs_t args, size_t nargsf, PyObject* kwds, CallContext* ctxt)
5860
{
59-
6061
// setup as necessary
6162
if (fArgsRequired == -1 && !this->Initialize(ctxt))
6263
return nullptr; // important: 0, not Py_None
@@ -78,15 +79,6 @@ PyObject* CPyCppyy::CPPConstructor::Call(CPPInstance*& self,
7879
return nullptr;
7980
}
8081

81-
const auto cppScopeFlags = ((CPPScope*)Py_TYPE(self))->fFlags;
82-
83-
// Do nothing if the constructor is explicit and we are in an implicit
84-
// conversion context. We recognize this by checking the CPPScope::kNoImplicit
85-
// flag, as further implicit conversions are disabled to prevent infinite
86-
// recursion. See also the ConvertImplicit() helper in Converters.cxx.
87-
if((cppScopeFlags & CPPScope::kNoImplicit) && Cppyy::IsExplicit(GetMethod()))
88-
return nullptr;
89-
9082
// self provides the python context for lifelines
9183
if (!ctxt->fPyContext)
9284
ctxt->fPyContext = (PyObject*)cargs.fSelf; // no Py_INCREF as no ownership
@@ -135,7 +127,7 @@ PyObject* CPyCppyy::CPPConstructor::Call(CPPInstance*& self,
135127

136128
} else {
137129
// translate the arguments
138-
if (cppScopeFlags & CPPScope::kNoImplicit)
130+
if (((CPPClass*)Py_TYPE(self))->fFlags & CPPScope::kNoImplicit)
139131
ctxt->fFlags |= CallContext::kNoImplicit;
140132
if (!this->ConvertAndSetArgs(cargs.fArgs, cargs.fNArgsf, ctxt))
141133
return nullptr;
@@ -182,6 +174,7 @@ PyObject* CPyCppyy::CPPConstructor::Call(CPPInstance*& self,
182174
return nullptr;
183175
}
184176

177+
185178
//----------------------------------------------------------------------------
186179
CPyCppyy::CPPMultiConstructor::CPPMultiConstructor(Cppyy::TCppScope_t scope, Cppyy::TCppMethod_t method) :
187180
CPPConstructor(scope, method)

bindings/pyroot/cppyy/CPyCppyy/src/CPPDataMember.cxx

Lines changed: 50 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "PyStrings.h"
55
#include "CPPDataMember.h"
66
#include "CPPInstance.h"
7+
#include "CPPEnum.h"
78
#include "Dimensions.h"
89
#include "LowLevelViews.h"
910
#include "ProxyWrappers.h"
@@ -47,30 +48,23 @@ static PyObject* dm_get(CPPDataMember* dm, CPPInstance* pyobj, PyObject* /* kls
4748
}
4849
}
4950

50-
// non-initialized or public data accesses through class (e.g. by help())
51-
void* address = dm->GetAddress(pyobj);
52-
if (!address || (intptr_t)address == -1 /* Cling error */)
53-
return nullptr;
5451

5552
if (dm->fFlags & (kIsEnumPrep | kIsEnumType)) {
5653
if (dm->fFlags & kIsEnumPrep) {
5754
// still need to do lookup; only ever try this once, then fallback on converter
5855
dm->fFlags &= ~kIsEnumPrep;
5956

6057
// fDescription contains the full name of the actual enum value object
61-
const std::string& lookup = CPyCppyy_PyText_AsString(dm->fDescription);
62-
const std::string& enum_type = TypeManip::extract_namespace(lookup);
63-
const std::string& enum_scope = TypeManip::extract_namespace(enum_type);
58+
const Cppyy::TCppScope_t enum_type = Cppyy::GetParentScope(dm->fScope);
59+
const Cppyy::TCppScope_t enum_scope = Cppyy::GetParentScope(enum_type);
6460

65-
PyObject* pyscope = nullptr;
66-
if (enum_scope.empty()) pyscope = GetScopeProxy(Cppyy::gGlobalScope);
67-
else pyscope = CreateScopeProxy(enum_scope);
61+
PyObject* pyscope = CreateScopeProxy(enum_scope);
6862
if (pyscope) {
69-
PyObject* pyEnumType = PyObject_GetAttrString(pyscope,
70-
enum_type.substr(enum_scope.size() ? enum_scope.size()+2 : 0, std::string::npos).c_str());
63+
PyObject* pyEnumType =
64+
PyObject_GetAttrString(pyscope, Cppyy::GetFinalName(enum_type).c_str());
7165
if (pyEnumType) {
72-
PyObject* pyval = PyObject_GetAttrString(pyEnumType,
73-
lookup.substr(enum_type.size()+2, std::string::npos).c_str());
66+
PyObject* pyval =
67+
PyObject_GetAttrString(pyEnumType, Cppyy::GetFinalName(dm->fScope).c_str());
7468
Py_DECREF(pyEnumType);
7569
if (pyval) {
7670
Py_DECREF(dm->fDescription);
@@ -88,7 +82,16 @@ static PyObject* dm_get(CPPDataMember* dm, CPPInstance* pyobj, PyObject* /* kls
8882
Py_INCREF(dm->fDescription);
8983
return dm->fDescription;
9084
}
85+
86+
if (Cppyy::IsEnumConstant(dm->fScope)) {
87+
// anonymous enum
88+
return pyval_from_enum(Cppyy::ResolveEnum(dm->fScope), nullptr, nullptr, dm->fScope);
89+
}
9190
}
91+
// non-initialized or public data accesses through class (e.g. by help())
92+
void* address = dm->GetAddress(pyobj);
93+
if (!address || (intptr_t)address == -1 /* Cling error */)
94+
return nullptr;
9295

9396
if (dm->fConverter != 0) {
9497
PyObject* result = dm->fConverter->FromMemory((dm->fFlags & kIsArrayType) ? &address : address);
@@ -319,53 +322,54 @@ PyTypeObject CPPDataMember_Type = {
319322

320323

321324
//- public members -----------------------------------------------------------
322-
void CPyCppyy::CPPDataMember::Set(Cppyy::TCppScope_t scope, Cppyy::TCppIndex_t idata)
325+
void CPyCppyy::CPPDataMember::Set(Cppyy::TCppScope_t scope, Cppyy::TCppScope_t data)
323326
{
324-
fEnclosingScope = scope;
325-
fOffset = Cppyy::GetDatamemberOffset(scope, idata); // TODO: make lazy
326-
fFlags = Cppyy::IsStaticData(scope, idata) ? kIsStaticData : 0;
327-
328-
std::vector<dim_t> dims;
329-
int ndim = 0; Py_ssize_t size = 0;
330-
while (0 < (size = Cppyy::GetDimensionSize(scope, idata, ndim))) {
331-
ndim += 1;
332-
if (size == INT_MAX) // meaning: incomplete array type
333-
size = UNKNOWN_SIZE;
334-
if (ndim == 1) dims.reserve(4);
335-
dims.push_back((dim_t)size);
327+
if (Cppyy::IsLambdaClass(Cppyy::GetDatamemberType(data))) {
328+
fScope = Cppyy::WrapLambdaFromVariable(data);
329+
} else {
330+
fScope = data;
336331
}
337-
if (!dims.empty())
338-
fFlags |= kIsArrayType;
339332

340-
const std::string name = Cppyy::GetDatamemberName(scope, idata);
341-
fFullType = Cppyy::GetDatamemberType(scope, idata);
342-
if (Cppyy::IsEnumData(scope, idata)) {
333+
fEnclosingScope = scope;
334+
fOffset = Cppyy::GetDatamemberOffset(fScope, fScope == data ? scope : Cppyy::GetScope("__cppyy_internal_wrap_g")); // XXX: Check back here // TODO: make lazy
335+
fFlags = Cppyy::IsStaticDatamember(fScope) ? kIsStaticData : 0;
336+
337+
const std::string name = Cppyy::GetFinalName(fScope);
338+
Cppyy::TCppType_t type;
339+
340+
341+
if (Cppyy::IsEnumConstant(fScope)) {
342+
type = Cppyy::GetEnumConstantType(fScope);
343+
fFullType = Cppyy::GetTypeAsString(type);
343344
if (fFullType.find("(anonymous)") == std::string::npos &&
344345
fFullType.find("(unnamed)") == std::string::npos) {
345346
// repurpose fDescription for lazy lookup of the enum later
346347
fDescription = CPyCppyy_PyText_FromString((fFullType + "::" + name).c_str());
347348
fFlags |= kIsEnumPrep;
348349
}
349-
fFullType = Cppyy::ResolveEnum(fFullType);
350-
fFlags |= kIsConstData;
351-
} else if (Cppyy::IsConstData(scope, idata)) {
350+
type = Cppyy::ResolveType(type);
352351
fFlags |= kIsConstData;
352+
} else {
353+
type = Cppyy::GetDatamemberType(fScope);
354+
fFullType = Cppyy::GetTypeAsString(type);
355+
356+
// Get the integer type if it's an enum
357+
if (Cppyy::IsEnumType(type))
358+
type = Cppyy::ResolveType(type);
359+
360+
if (Cppyy::IsConstVar(fScope))
361+
fFlags |= kIsConstData;
353362
}
354363

355-
// if this data member is an array, the conversion needs to be pointer to object for instances,
356-
// to prevent the need for copying in the conversion; furthermore, fixed arrays' full type for
357-
// builtins are not declared as such if more than 1-dim (TODO: fix in clingwrapper)
358-
if (!dims.empty() && fFullType.back() != '*') {
359-
if (Cppyy::GetScope(fFullType)) fFullType += '*';
360-
else if (fFullType.back() != ']') {
361-
for (auto d: dims) fFullType += d == UNKNOWN_SIZE ? "*" : "[]";
362-
}
363-
}
364+
std::vector<dim_t> dims = Cppyy::GetDimensions(type);
365+
366+
if (!dims.empty())
367+
fFlags |= kIsArrayType;
364368

365369
if (dims.empty())
366-
fConverter = CreateConverter(fFullType);
370+
fConverter = CreateConverter(type, 0);
367371
else
368-
fConverter = CreateConverter(fFullType, {(dim_t)dims.size(), dims.data()});
372+
fConverter = CreateConverter(type, {(dim_t)dims.size(), dims.data()});
369373

370374
if (!(fFlags & kIsEnumPrep))
371375
fDescription = CPyCppyy_PyText_FromString(name.c_str());

bindings/pyroot/cppyy/CPyCppyy/src/CPPDataMember.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class CPPInstance;
1414

1515
class CPPDataMember {
1616
public:
17-
void Set(Cppyy::TCppScope_t scope, Cppyy::TCppIndex_t idata);
17+
void Set(Cppyy::TCppScope_t scope, Cppyy::TCppScope_t var);
1818
void Set(Cppyy::TCppScope_t scope, const std::string& name, void* address);
1919

2020
std::string GetName();
@@ -25,6 +25,7 @@ class CPPDataMember {
2525
intptr_t fOffset;
2626
long fFlags;
2727
Converter* fConverter;
28+
Cppyy::TCppScope_t fScope;
2829
Cppyy::TCppScope_t fEnclosingScope;
2930
PyObject* fDescription;
3031
PyObject* fDoc;
@@ -55,12 +56,12 @@ inline bool CPPDataMember_CheckExact(T* object)
5556

5657
//- creation -----------------------------------------------------------------
5758
inline CPPDataMember* CPPDataMember_New(
58-
Cppyy::TCppScope_t scope, Cppyy::TCppIndex_t idata)
59+
Cppyy::TCppScope_t scope, Cppyy::TCppScope_t var)
5960
{
6061
// Create an initialize a new property descriptor, given the C++ datum.
6162
CPPDataMember* pyprop =
6263
(CPPDataMember*)CPPDataMember_Type.tp_new(&CPPDataMember_Type, nullptr, nullptr);
63-
pyprop->Set(scope, idata);
64+
pyprop->Set(scope, var);
6465
return pyprop;
6566
}
6667

0 commit comments

Comments
 (0)