ROOT
master
Reference Guide
Loading...
Searching...
No Matches
TupleOfInstances.cxx
Go to the documentation of this file.
1
// Bindings
2
#include "
CPyCppyy.h
"
3
#include "
TupleOfInstances.h
"
4
#include "
ProxyWrappers.h
"
5
6
7
namespace
{
8
9
typedef
struct
{
10
PyObject_HEAD
11
Cppyy::TCppType_t
ia_klass;
12
void
* ia_array_start;
13
Py_ssize_t
ia_pos;
14
Py_ssize_t
ia_len;
15
Py_ssize_t
ia_stride;
16
} ia_iterobject;
17
18
static
PyObject
*
ia_iternext
(ia_iterobject*
ia
) {
19
if
(
ia
->ia_len != (
Py_ssize_t
)-1 &&
ia
->ia_pos >=
ia
->ia_len) {
20
ia
->ia_pos = 0;
// debatable, but since the iterator is cached, this
21
return
nullptr
;
// allows for multiple conversions to e.g. a tuple
22
}
else
if
(
ia
->ia_stride == 0 &&
ia
->ia_pos != 0) {
23
PyErr_SetString
(
PyExc_ReferenceError
,
"no stride available for indexing"
);
24
return
nullptr
;
25
}
26
PyObject
*
result
=
CPyCppyy::BindCppObjectNoCast
(
27
(
char
*)
ia
->ia_array_start +
ia
->ia_pos*
ia
->ia_stride,
ia
->ia_klass);
28
ia
->ia_pos += 1;
29
return
result
;
30
}
31
32
static
int
ia_traverse
(ia_iterobject*,
visitproc
,
void
*) {
33
return
0;
34
}
35
36
static
PyObject
*
ia_getsize
(ia_iterobject*
ia
,
void
*) {
37
return
PyInt_FromSsize_t
(
ia
->ia_len);
38
}
39
40
static
int
ia_setsize
(ia_iterobject*
ia
,
PyObject
*
pysize
,
void
*) {
41
Py_ssize_t
size
=
PyInt_AsSsize_t
(
pysize
);
42
if
(
size
== (
Py_ssize_t
)-1 &&
PyErr_Occurred
())
43
return
-1;
44
ia
->ia_len =
size
;
45
return
0;
46
}
47
48
static
PyGetSetDef
ia_getset
[] = {
49
{(
char
*)
"size"
, (
getter
)
ia_getsize
, (
setter
)
ia_setsize
,
50
(
char
*)
"set size of array to which this iterator refers"
,
nullptr
},
51
{(
char
*)
nullptr
,
nullptr
,
nullptr
,
nullptr
,
nullptr
}
52
};
53
54
55
static
Py_ssize_t
ia_length
(ia_iterobject*
ia
)
56
{
57
return
ia
->ia_len;
58
}
59
60
static
PyObject
*
ia_subscript
(ia_iterobject*
ia
,
PyObject
*
pyidx
)
61
{
62
// Subscripting the iterator allows direct access through indexing on arrays
63
// that do not have a defined length. This way, the return from accessing such
64
// an array as a data member can both be used in a loop and directly.
65
Py_ssize_t
idx =
PyInt_AsSsize_t
(
pyidx
);
66
if
(idx == (
Py_ssize_t
)-1 &&
PyErr_Occurred
())
67
return
nullptr
;
68
69
if
(
ia
->ia_len != (
Py_ssize_t
)-1 && (
idx < 0 || ia->
ia_len <= idx)) {
70
PyErr_SetString
(
PyExc_IndexError
,
"index out of range"
);
71
return
nullptr
;
72
}
73
74
return
CPyCppyy::BindCppObjectNoCast
(
75
(
char
*)
ia
->ia_array_start +
ia
->ia_pos*
ia
->ia_stride,
ia
->ia_klass);
76
}
77
78
static
PyMappingMethods
ia_as_mapping
= {
79
(
lenfunc
)
ia_length
,
// mp_length
80
(binaryfunc)
ia_subscript
,
// mp_subscript
81
(
objobjargproc
)
nullptr
,
// mp_ass_subscript
82
};
83
84
}
// unnamed namespace
85
86
87
namespace
CPyCppyy
{
88
89
PyTypeObject
InstanceArrayIter_Type
= {
90
PyVarObject_HEAD_INIT
(&
PyType_Type
, 0)
91
(
char
*)
"cppyy.instancearrayiter"
,
// tp_name
92
sizeof
(ia_iterobject),
// tp_basicsize
93
0,
94
(
destructor
)
PyObject_GC_Del
,
// tp_dealloc
95
0, 0, 0, 0, 0, 0, 0,
96
&
ia_as_mapping
,
// tp_as_mapping
97
0, 0, 0, 0, 0, 0,
98
Py_TPFLAGS_DEFAULT
|
99
Py_TPFLAGS_HAVE_GC
,
// tp_flags
100
0,
101
(
traverseproc
)
ia_traverse
,
// tp_traverse
102
0, 0, 0,
103
PyObject_SelfIter
,
// tp_iter
104
(
iternextfunc
)
ia_iternext
,
// tp_iternext
105
0, 0,
106
ia_getset
,
// tp_getset
107
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
108
#
if
PY_VERSION_HEX
>= 0x02030000
109
, 0
// tp_del
110
#
endif
111
#
if
PY_VERSION_HEX
>= 0x02060000
112
, 0
// tp_version_tag
113
#
endif
114
#
if
PY_VERSION_HEX
>= 0x03040000
115
, 0
// tp_finalize
116
#
endif
117
#
if
PY_VERSION_HEX
>= 0x03080000
118
, 0
// tp_vectorcall
119
#
endif
120
CPYCPPYY_PYTYPE_TAIL
121
};
122
123
124
//= support for C-style arrays of objects ====================================
125
PyObject
*
TupleOfInstances_New
(
126
Cppyy::TCppObject_t
address,
Cppyy::TCppType_t
klass
,
cdims_t
dims
)
127
{
128
// recursively set up tuples of instances on all dimensions
129
if
(
dims
.ndim() ==
UNKNOWN_SIZE
||
dims
[0] ==
UNKNOWN_SIZE
/* unknown shape or size */
) {
130
// no known length ... return an iterable object and let the user figure it out
131
ia_iterobject*
ia
=
PyObject_GC_New
(ia_iterobject, &
InstanceArrayIter_Type
);
132
if
(!
ia
)
return
nullptr
;
133
134
ia
->ia_klass =
klass
;
135
ia
->ia_array_start = address;
136
ia
->ia_pos = 0;
137
ia
->ia_len = -1;
138
ia
->ia_stride =
Cppyy::SizeOf
(
klass
);
139
140
PyObject_GC_Track
(
ia
);
141
return
(
PyObject
*)
ia
;
142
}
else
if
(1 <
dims
.ndim()) {
143
// not the innermost dimension, descend one level
144
size_t
block_size
= 0;
145
for
(
Py_ssize_t
i = 1; i <
dims
.ndim(); ++i)
block_size
+= (
size_t
)
dims
[i];
146
block_size
*=
Cppyy::SizeOf
(
klass
);
147
148
Py_ssize_t
nelems
=
dims
[0];
149
PyObject
*
tup
=
PyTuple_New
(
nelems
);
150
for
(
Py_ssize_t
i = 0; i <
nelems
; ++i) {
151
PyTuple_SetItem
(
tup
, i,
TupleOfInstances_New
(
152
(
char
*)address + i*
block_size
,
klass
,
dims
.sub()));
153
}
154
return
tup
;
155
}
else
{
156
// innermost dimension: construct tuple
157
int
nelems
= (
int
)
dims
[0];
158
size_t
block_size
=
Cppyy::SizeOf
(
klass
);
159
if
(
block_size
== 0) {
160
PyErr_Format
(
PyExc_TypeError
,
161
"can not determine size of type \"%s\" for array indexing"
,
162
Cppyy::GetScopedFinalName
(
klass
).c_str());
163
return
nullptr
;
164
}
165
166
// TODO: the extra copy is inefficient, but it appears that the only way to
167
// initialize a subclass of a tuple is through a sequence
168
PyObject
*
tup
=
PyTuple_New
(
nelems
);
169
for
(
int
i = 0; i <
nelems
; ++i) {
170
// TODO: there's an assumption here that there is no padding, which is bound
171
// to be incorrect in certain cases
172
PyTuple_SetItem
(
tup
, i,
173
BindCppObjectNoCast
((
char
*)address + i*
block_size
,
klass
));
174
// Note: objects are bound as pointers, yet since the pointer value stays in
175
// place, updates propagate just as if they were bound by-reference
176
}
177
178
PyObject
* args =
PyTuple_New
(1);
179
Py_INCREF
(
tup
);
PyTuple_SET_ITEM
(args, 0,
tup
);
180
PyObject
*
arr
=
PyTuple_Type
.tp_new(&
TupleOfInstances_Type
, args,
nullptr
);
181
182
Py_DECREF
(args);
183
// tup ref eaten by SET_ITEM on args
184
185
return
arr
;
186
}
187
188
// never get here
189
return
nullptr
;
190
}
191
192
//= CPyCppyy custom tuple-like array type ====================================
193
PyTypeObject
TupleOfInstances_Type
= {
194
PyVarObject_HEAD_INIT
(&
PyType_Type
, 0)
195
(
char
*)
"cppyy.InstancesArray"
,
// tp_name
196
0,
// tp_basicsize
197
0,
// tp_itemsize
198
0,
// tp_dealloc
199
0,
// tp_vectorcall_offset / tp_print
200
0,
// tp_getattr
201
0,
// tp_setattr
202
0,
// tp_as_async / tp_compare
203
0,
// tp_repr
204
0,
// tp_as_number
205
0,
// tp_as_sequence
206
0,
// tp_as_mapping
207
0,
// tp_hash
208
0,
// tp_call
209
0,
// tp_str
210
0,
// tp_getattro
211
0,
// tp_setattro
212
0,
// tp_as_buffer
213
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_CHECKTYPES
|
214
Py_TPFLAGS_BASETYPE
,
// tp_flags
215
(
char
*)
"array of C++ instances"
,
// tp_doc
216
0,
// tp_traverse
217
0,
// tp_clear
218
0,
// tp_richcompare
219
0,
// tp_weaklistoffset
220
0,
// tp_iter
221
0,
// tp_iternext
222
0,
// tp_methods
223
0,
// tp_members
224
0,
// tp_getset
225
&
PyTuple_Type
,
// tp_base
226
0,
// tp_dict
227
0,
// tp_descr_get
228
0,
// tp_descr_set
229
0,
// tp_dictoffset
230
0,
// tp_init
231
0,
// tp_alloc
232
0,
// tp_new
233
0,
// tp_free
234
0,
// tp_is_gc
235
0,
// tp_bases
236
0,
// tp_mro
237
0,
// tp_cache
238
0,
// tp_subclasses
239
0
// tp_weaklist
240
#if PY_VERSION_HEX >= 0x02030000
241
, 0
// tp_del
242
#endif
243
#if PY_VERSION_HEX >= 0x02060000
244
, 0
// tp_version_tag
245
#endif
246
#if PY_VERSION_HEX >= 0x03040000
247
, 0
// tp_finalize
248
#endif
249
#if PY_VERSION_HEX >= 0x03080000
250
, 0
// tp_vectorcall
251
#endif
252
CPYCPPYY_PYTYPE_TAIL
253
};
254
255
}
// namespace CPyCppyy
CPyCppyy.h
PyInt_FromSsize_t
#define PyInt_FromSsize_t
Definition
CPyCppyy.h:217
lenfunc
#define lenfunc
Definition
CPyCppyy.h:224
Py_ssize_t
int Py_ssize_t
Definition
CPyCppyy.h:215
PyInt_AsSsize_t
#define PyInt_AsSsize_t
Definition
CPyCppyy.h:216
CPYCPPYY_PYTYPE_TAIL
#define CPYCPPYY_PYTYPE_TAIL
Definition
CPyCppyy.h:412
PyVarObject_HEAD_INIT
#define PyVarObject_HEAD_INIT(type, size)
Definition
CPyCppyy.h:194
ProxyWrappers.h
PyObject
_object PyObject
Definition
PyMethodBase.h:36
size
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
TRangeDynCast
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Definition
TCollection.h:360
result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Definition
TGWin32VirtualXProxy.cxx:174
TupleOfInstances.h
CPyCppyy::Dimensions
Definition
API.h:91
ROOT::Detail::TRangeCast
Definition
TCollection.h:313
int
CPyCppyy
Definition
callcontext.h:13
CPyCppyy::BindCppObjectNoCast
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
Definition
ProxyWrappers.cxx:823
CPyCppyy::UNKNOWN_SIZE
static const dim_t UNKNOWN_SIZE
Definition
Dimensions.h:14
CPyCppyy::TupleOfInstances_New
PyObject * TupleOfInstances_New(Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, cdims_t dims)
Definition
TupleOfInstances.cxx:125
CPyCppyy::InstanceArrayIter_Type
PyTypeObject InstanceArrayIter_Type
Definition
TupleOfInstances.cxx:89
CPyCppyy::TupleOfInstances_Type
PyTypeObject TupleOfInstances_Type
Representation of C-style array of instances.
Definition
TupleOfInstances.cxx:193
Cppyy::SizeOf
RPY_EXPORTED size_t SizeOf(TCppType_t klass)
Definition
clingwrapper.cxx:834
Cppyy::TCppObject_t
void * TCppObject_t
Definition
cpp_cppyy.h:37
Cppyy::TCppType_t
TCppScope_t TCppType_t
Definition
cpp_cppyy.h:35
Cppyy::GetScopedFinalName
RPY_EXPORTED std::string GetScopedFinalName(TCppType_t type)
Definition
clingwrapper.cxx:1494
bindings
pyroot
cppyy
CPyCppyy
src
TupleOfInstances.cxx
ROOTmaster - Reference Guide Generated on Fri Jun 12 2026 16:00:58 (GVA Time) using Doxygen 1.10.0