ROOT
v6-32
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
#
if
PY_VERSION_HEX
>= 0x030c0000
121
, 0
// tp_watched
122
#
endif
123
};
124
125
126
//= support for C-style arrays of objects ====================================
127
PyObject
*
TupleOfInstances_New
(
128
Cppyy::TCppObject_t
address,
Cppyy::TCppType_t
klass
,
cdims_t
dims
)
129
{
130
// recursively set up tuples of instances on all dimensions
131
if
(
dims
.ndim() ==
UNKNOWN_SIZE
||
dims
[0] ==
UNKNOWN_SIZE
/* unknown shape or size */
) {
132
// no known length ... return an iterable object and let the user figure it out
133
ia_iterobject*
ia
=
PyObject_GC_New
(ia_iterobject, &
InstanceArrayIter_Type
);
134
if
(!
ia
)
return
nullptr
;
135
136
ia
->ia_klass =
klass
;
137
ia
->ia_array_start = address;
138
ia
->ia_pos = 0;
139
ia
->ia_len = -1;
140
ia
->ia_stride =
Cppyy::SizeOf
(
klass
);
141
142
PyObject_GC_Track
(
ia
);
143
return
(
PyObject
*)
ia
;
144
}
else
if
(1 <
dims
.ndim()) {
145
// not the innermost dimension, descend one level
146
size_t
block_size
= 0;
147
for
(
Py_ssize_t
i = 1; i <
dims
.ndim(); ++i)
block_size
+= (
size_t
)
dims
[i];
148
block_size
*=
Cppyy::SizeOf
(
klass
);
149
150
Py_ssize_t
nelems
=
dims
[0];
151
PyObject
*
tup
=
PyTuple_New
(
nelems
);
152
for
(
Py_ssize_t
i = 0; i <
nelems
; ++i) {
153
PyTuple_SetItem
(
tup
, i,
TupleOfInstances_New
(
154
(
char
*)address + i*
block_size
,
klass
,
dims
.sub()));
155
}
156
return
tup
;
157
}
else
{
158
// innermost dimension: construct tuple
159
int
nelems
= (
int
)
dims
[0];
160
size_t
block_size
=
Cppyy::SizeOf
(
klass
);
161
if
(
block_size
== 0) {
162
PyErr_Format
(
PyExc_TypeError
,
163
"can not determine size of type \"%s\" for array indexing"
,
164
Cppyy::GetScopedFinalName
(
klass
).c_str());
165
return
nullptr
;
166
}
167
168
// TODO: the extra copy is inefficient, but it appears that the only way to
169
// initialize a subclass of a tuple is through a sequence
170
PyObject
*
tup
=
PyTuple_New
(
nelems
);
171
for
(
int
i = 0; i <
nelems
; ++i) {
172
// TODO: there's an assumption here that there is no padding, which is bound
173
// to be incorrect in certain cases
174
PyTuple_SetItem
(
tup
, i,
175
BindCppObjectNoCast
((
char
*)address + i*
block_size
,
klass
));
176
// Note: objects are bound as pointers, yet since the pointer value stays in
177
// place, updates propagate just as if they were bound by-reference
178
}
179
180
PyObject
* args =
PyTuple_New
(1);
181
Py_INCREF
(
tup
);
PyTuple_SET_ITEM
(args, 0,
tup
);
182
PyObject
*
arr
=
PyTuple_Type
.tp_new(&
TupleOfInstances_Type
, args,
nullptr
);
183
184
Py_DECREF
(args);
185
// tup ref eaten by SET_ITEM on args
186
187
return
arr
;
188
}
189
190
// never get here
191
return
nullptr
;
192
}
193
194
//= CPyCppyy custom tuple-like array type ====================================
195
PyTypeObject
TupleOfInstances_Type
= {
196
PyVarObject_HEAD_INIT
(&
PyType_Type
, 0)
197
(
char
*)
"cppyy.InstancesArray"
,
// tp_name
198
0,
// tp_basicsize
199
0,
// tp_itemsize
200
0,
// tp_dealloc
201
0,
// tp_vectorcall_offset / tp_print
202
0,
// tp_getattr
203
0,
// tp_setattr
204
0,
// tp_as_async / tp_compare
205
0,
// tp_repr
206
0,
// tp_as_number
207
0,
// tp_as_sequence
208
0,
// tp_as_mapping
209
0,
// tp_hash
210
0,
// tp_call
211
0,
// tp_str
212
0,
// tp_getattro
213
0,
// tp_setattro
214
0,
// tp_as_buffer
215
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_CHECKTYPES
|
216
Py_TPFLAGS_BASETYPE
,
// tp_flags
217
(
char
*)
"array of C++ instances"
,
// tp_doc
218
0,
// tp_traverse
219
0,
// tp_clear
220
0,
// tp_richcompare
221
0,
// tp_weaklistoffset
222
0,
// tp_iter
223
0,
// tp_iternext
224
0,
// tp_methods
225
0,
// tp_members
226
0,
// tp_getset
227
&
PyTuple_Type
,
// tp_base
228
0,
// tp_dict
229
0,
// tp_descr_get
230
0,
// tp_descr_set
231
0,
// tp_dictoffset
232
0,
// tp_init
233
0,
// tp_alloc
234
0,
// tp_new
235
0,
// tp_free
236
0,
// tp_is_gc
237
0,
// tp_bases
238
0,
// tp_mro
239
0,
// tp_cache
240
0,
// tp_subclasses
241
0
// tp_weaklist
242
#if PY_VERSION_HEX >= 0x02030000
243
, 0
// tp_del
244
#endif
245
#if PY_VERSION_HEX >= 0x02060000
246
, 0
// tp_version_tag
247
#endif
248
#if PY_VERSION_HEX >= 0x03040000
249
, 0
// tp_finalize
250
#endif
251
#if PY_VERSION_HEX >= 0x03080000
252
, 0
// tp_vectorcall
253
#endif
254
#if PY_VERSION_HEX >= 0x030c0000
255
, 0
// tp_watched
256
#endif
257
};
258
259
}
// 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
PyVarObject_HEAD_INIT
#define PyVarObject_HEAD_INIT(type, size)
Definition
CPyCppyy.h:194
ProxyWrappers.h
PyObject
_object PyObject
Definition
PyMethodBase.h:43
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:358
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:92
ROOT::Detail::TRangeCast
Definition
TCollection.h:311
int
CPyCppyy
Definition
callcontext.h:10
CPyCppyy::BindCppObjectNoCast
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
Definition
ProxyWrappers.cxx:825
CPyCppyy::UNKNOWN_SIZE
static const dim_t UNKNOWN_SIZE
Definition
Dimensions.h:11
CPyCppyy::TupleOfInstances_New
PyObject * TupleOfInstances_New(Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, cdims_t dims)
Definition
TupleOfInstances.cxx:127
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:195
Cppyy::SizeOf
RPY_EXPORTED size_t SizeOf(TCppType_t klass)
Definition
clingwrapper.cxx:639
Cppyy::TCppObject_t
void * TCppObject_t
Definition
cpp_cppyy.h:21
Cppyy::TCppType_t
TCppScope_t TCppType_t
Definition
cpp_cppyy.h:19
Cppyy::GetScopedFinalName
RPY_EXPORTED std::string GetScopedFinalName(TCppType_t type)
Definition
clingwrapper.cxx:1242
bindings
pyroot
cppyy
CPyCppyy
src
TupleOfInstances.cxx
ROOT v6-32 - Reference Guide Generated on Wed Sep 3 2025 04:17:22 (GVA Time) using Doxygen 1.10.0