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