@@ -230,6 +230,13 @@ void CPyCppyy::op_dealloc_nofree(CPPInstance* pyobj) {
230230
231231namespace CPyCppyy {
232232
233+ // ----------------------------------------------------------------------------
234+ static int op_traverse (CPPInstance* /* pyobj*/ , visitproc /* visit*/ , void * /* arg*/ )
235+ {
236+ return 0 ;
237+ }
238+
239+
233240// = CPyCppyy object proxy null-ness checking =================================
234241static int op_nonzero (CPPInstance* self)
235242{
@@ -314,6 +321,12 @@ void CPyCppyy::CPPInstance::CastToArray(Py_ssize_t sz)
314321 ARRAY_SIZE (this ) = sz;
315322}
316323
324+ Py_ssize_t CPyCppyy::CPPInstance::ArrayLength () {
325+ if (!(fFlags & kIsArray ))
326+ return -1 ;
327+ return (Py_ssize_t)ARRAY_SIZE (this );
328+ }
329+
317330static PyObject* op_reshape (CPPInstance* self, PyObject* shape)
318331{
319332// Allow the user to fix up the actual (type-strided) size of the buffer.
@@ -323,14 +336,17 @@ static PyObject* op_reshape(CPPInstance* self, PyObject* shape)
323336 }
324337
325338 long sz = PyLong_AsLong (PyTuple_GET_ITEM (shape, 0 ));
326- if (sz == -1 ) return nullptr ;
339+ if (sz <= 0 ) {
340+ PyErr_SetString (PyExc_ValueError, " array length must be positive" );
341+ return nullptr ;
342+ }
327343
328344 self->CastToArray (sz);
329345
330346 Py_RETURN_NONE;
331347}
332348
333- static PyObject* op_getitem (CPPInstance* self, PyObject* pyidx )
349+ static PyObject* op_item (CPPInstance* self, Py_ssize_t idx )
334350{
335351// In C, it is common to represent an array of structs as a pointer to the first
336352// object in the array. If the caller indexes a pointer to an object that does not
@@ -374,6 +390,21 @@ static PyObject* op_getitem(CPPInstance* self, PyObject* pyidx)
374390 return BindCppObjectNoCast (indexed_obj, ((CPPClass*)Py_TYPE (self))->fCppType , flags);
375391}
376392
393+ // - sequence methods --------------------------------------------------------
394+ static PySequenceMethods op_as_sequence = {
395+ 0 , // sq_length
396+ 0 , // sq_concat
397+ 0 , // sq_repeat
398+ (ssizeargfunc)op_item, // sq_item
399+ 0 , // sq_slice
400+ 0 , // sq_ass_item
401+ 0 , // sq_ass_slice
402+ 0 , // sq_contains
403+ 0 , // sq_inplace_concat
404+ 0 , // sq_inplace_repeat
405+ };
406+
407+
377408// ----------------------------------------------------------------------------
378409static PyMethodDef op_methods[] = {
379410 {(char *)" __destruct__" , (PyCFunction)op_destruct, METH_NOARGS,
@@ -1025,7 +1056,7 @@ PyTypeObject CPPInstance_Type = {
10251056 0 , // tp_as_async / tp_compare
10261057 (reprfunc)op_repr, // tp_repr
10271058 &op_as_number, // tp_as_number
1028- 0 , // tp_as_sequence
1059+ &op_as_sequence, // tp_as_sequence
10291060 0 , // tp_as_mapping
10301061 (hashfunc)op_hash, // tp_hash
10311062 0 , // tp_call
@@ -1035,9 +1066,10 @@ PyTypeObject CPPInstance_Type = {
10351066 0 , // tp_as_buffer
10361067 Py_TPFLAGS_DEFAULT |
10371068 Py_TPFLAGS_BASETYPE |
1038- Py_TPFLAGS_CHECKTYPES, // tp_flags
1069+ Py_TPFLAGS_CHECKTYPES |
1070+ Py_TPFLAGS_HAVE_GC, // tp_flags
10391071 (char *)" cppyy object proxy (internal)" , // tp_doc
1040- 0 , // tp_traverse
1072+ (traverseproc)op_traverse, // tp_traverse
10411073 (inquiry)op_clear, // tp_clear
10421074 (richcmpfunc)op_richcompare, // tp_richcompare
10431075 0 , // tp_weaklistoffset
@@ -1070,6 +1102,12 @@ PyTypeObject CPPInstance_Type = {
10701102#if PY_VERSION_HEX >= 0x03040000
10711103 , 0 // tp_finalize
10721104#endif
1105+ #if PY_VERSION_HEX >= 0x03080000
1106+ , 0 // tp_vectorcall
1107+ #endif
1108+ #if PY_VERSION_HEX >= 0x030c0000
1109+ , 0 // tp_watched
1110+ #endif
10731111};
10741112
10751113} // namespace CPyCppyy
0 commit comments