Skip to content

Commit 802afc2

Browse files
committed
Sync CustomPyTypes
1 parent ba42b46 commit 802afc2

File tree

2 files changed

+46
-10
lines changed

2 files changed

+46
-10
lines changed

src/CustomPyTypes.cxx

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,20 @@
66
#include "ProxyWrappers.h"
77
#include "PyStrings.h"
88

9+
// As of Python 3.12, we can't use the PyMethod_GET_FUNCTION and
10+
// PyMethod_GET_SELF macros anymore, as the contain asserts that check if the
11+
// Python type is actually PyMethod_Type. If the Python type is
12+
// CustomInstanceMethod_Type, we need our own macros. Technically they do they
13+
// same, because the actual C++ type of the PyObject is PyMethodObject anyway.
14+
#define CustomInstanceMethod_GET_SELF(meth) reinterpret_cast<PyMethodObject *>(meth)->im_self
15+
#define CustomInstanceMethod_GET_FUNCTION(meth) reinterpret_cast<PyMethodObject *>(meth)->im_func
916
#if PY_VERSION_HEX >= 0x03000000
1017
// TODO: this will break functionality
11-
#define PyMethod_GET_CLASS(meth) Py_None
18+
#define CustomInstanceMethod_GET_CLASS(meth) Py_None
19+
#else
20+
#define CustomInstanceMethod_GET_CLASS(meth) PyMethod_GET_CLASS(meth)
1221
#endif
1322

14-
1523
namespace CPyCppyy {
1624

1725
#if PY_VERSION_HEX < 0x03000000
@@ -156,6 +164,12 @@ PyTypeObject TypedefPointerToClass_Type = {
156164
#if PY_VERSION_HEX >= 0x03040000
157165
, 0 // tp_finalize
158166
#endif
167+
#if PY_VERSION_HEX >= 0x03080000
168+
, 0 // tp_vectorcall
169+
#endif
170+
#if PY_VERSION_HEX >= 0x030c0000
171+
, 0 // tp_watched
172+
#endif
159173
};
160174

161175
//= instancemethod object with a more efficient call function ================
@@ -237,13 +251,13 @@ static PyObject* im_call(PyObject* meth, PyObject* args, PyObject* kw)
237251
// into the list of arguments. However, the pythonized methods will then have
238252
// to undo that shuffling, which is inefficient. This method is the same as
239253
// the one for the instancemethod object, except for the shuffling.
240-
PyObject* self = PyMethod_GET_SELF(meth);
254+
PyObject* self = CustomInstanceMethod_GET_SELF(meth);
241255

242256
if (!self) {
243257
// unbound methods must be called with an instance of the class (or a
244258
// derived class) as first argument
245259
Py_ssize_t argc = PyTuple_GET_SIZE(args);
246-
PyObject* pyclass = PyMethod_GET_CLASS(meth);
260+
PyObject* pyclass = CustomInstanceMethod_GET_CLASS(meth);
247261
if (1 <= argc && PyObject_IsInstance(PyTuple_GET_ITEM(args, 0), pyclass) == 1) {
248262
self = PyTuple_GET_ITEM(args, 0);
249263

@@ -262,7 +276,7 @@ static PyObject* im_call(PyObject* meth, PyObject* args, PyObject* kw)
262276
} else
263277
Py_INCREF(args);
264278

265-
PyCFunctionObject* func = (PyCFunctionObject*)PyMethod_GET_FUNCTION(meth);
279+
PyCFunctionObject* func = (PyCFunctionObject*)CustomInstanceMethod_GET_FUNCTION(meth);
266280

267281
// the function is globally shared, so set and reset its "self" (ok, b/c of GIL)
268282
Py_INCREF(self);
@@ -279,10 +293,10 @@ static PyObject* im_descr_get(PyObject* meth, PyObject* obj, PyObject* pyclass)
279293
{
280294
// from instancemethod: don't rebind an already bound method, or an unbound method
281295
// of a class that's not a base class of pyclass
282-
if (PyMethod_GET_SELF(meth)
296+
if (CustomInstanceMethod_GET_SELF(meth)
283297
#if PY_VERSION_HEX < 0x03000000
284-
|| (PyMethod_GET_CLASS(meth) &&
285-
!PyObject_IsSubclass(pyclass, PyMethod_GET_CLASS(meth)))
298+
|| (CustomInstanceMethod_GET_CLASS(meth) &&
299+
!PyObject_IsSubclass(pyclass, CustomInstanceMethod_GET_CLASS(meth)))
286300
#endif
287301
) {
288302
Py_INCREF(meth);
@@ -292,7 +306,7 @@ static PyObject* im_descr_get(PyObject* meth, PyObject* obj, PyObject* pyclass)
292306
if (obj == Py_None)
293307
obj = nullptr;
294308

295-
return CustomInstanceMethod_New(PyMethod_GET_FUNCTION(meth), obj, pyclass);
309+
return CustomInstanceMethod_New(CustomInstanceMethod_GET_FUNCTION(meth), obj, pyclass);
296310
}
297311

298312
//= CPyCppyy custom instance method type =====================================
@@ -321,6 +335,12 @@ PyTypeObject CustomInstanceMethod_Type = {
321335
#if PY_VERSION_HEX >= 0x03040000
322336
, 0 // tp_finalize
323337
#endif
338+
#if PY_VERSION_HEX >= 0x03080000
339+
, 0 // tp_vectorcall
340+
#endif
341+
#if PY_VERSION_HEX >= 0x030c0000
342+
, 0 // tp_watched
343+
#endif
324344
};
325345

326346

@@ -372,6 +392,12 @@ PyTypeObject IndexIter_Type = {
372392
#if PY_VERSION_HEX >= 0x03040000
373393
, 0 // tp_finalize
374394
#endif
395+
#if PY_VERSION_HEX >= 0x03080000
396+
, 0 // tp_vectorcall
397+
#endif
398+
#if PY_VERSION_HEX >= 0x030c0000
399+
, 0 // tp_watched
400+
#endif
375401
};
376402

377403

@@ -394,7 +420,10 @@ static PyObject* vectoriter_iternext(vectoriterobject* vi) {
394420
// that objects in vectors are simple and thus do not need to maintain object identity
395421
// (or at least not during the loop anyway). This gains 2x in performance.
396422
Cppyy::TCppObject_t cppobj = (Cppyy::TCppObject_t)((ptrdiff_t)vi->vi_data + vi->vi_stride * vi->ii_pos);
397-
result = CPyCppyy::BindCppObjectNoCast(cppobj, vi->vi_klass, CPyCppyy::CPPInstance::kNoMemReg);
423+
if (vi->vi_flags & vectoriterobject::kIsPolymorphic)
424+
result = CPyCppyy::BindCppObject(*(void**)cppobj, vi->vi_klass, CPyCppyy::CPPInstance::kNoMemReg);
425+
else
426+
result = CPyCppyy::BindCppObjectNoCast(cppobj, vi->vi_klass, CPyCppyy::CPPInstance::kNoMemReg);
398427
if ((vi->vi_flags & vectoriterobject::kNeedLifeLine) && result)
399428
PyObject_SetAttr(result, PyStrings::gLifeLine, vi->ii_container);
400429
} else {
@@ -431,6 +460,12 @@ PyTypeObject VectorIter_Type = {
431460
#if PY_VERSION_HEX >= 0x03040000
432461
, 0 // tp_finalize
433462
#endif
463+
#if PY_VERSION_HEX >= 0x03080000
464+
, 0 // tp_vectorcall
465+
#endif
466+
#if PY_VERSION_HEX >= 0x030c0000
467+
, 0 // tp_watched
468+
#endif
434469
};
435470

436471
} // namespace CPyCppyy

src/CustomPyTypes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ struct vectoriterobject : public indexiterobject {
102102
enum EFlags {
103103
kDefault = 0x0000,
104104
kNeedLifeLine = 0x0001,
105+
kIsPolymorphic = 0x0002,
105106
};
106107
};
107108

0 commit comments

Comments
 (0)