@@ -158,6 +158,12 @@ static PyTypeObject PyNullPtr_t_Type = {
158158#if PY_VERSION_HEX >= 0x03040000
159159 , 0 // tp_finalize
160160#endif
161+ #if PY_VERSION_HEX >= 0x03080000
162+ , 0 // tp_vectorcall
163+ #endif
164+ #if PY_VERSION_HEX >= 0x030c0000
165+ , 0 // tp_watched
166+ #endif
161167};
162168
163169
@@ -192,6 +198,12 @@ static PyTypeObject PyDefault_t_Type = {
192198#if PY_VERSION_HEX >= 0x03040000
193199 , 0 // tp_finalize
194200#endif
201+ #if PY_VERSION_HEX >= 0x03080000
202+ , 0 // tp_vectorcall
203+ #endif
204+ #if PY_VERSION_HEX >= 0x030c0000
205+ , 0 // tp_watched
206+ #endif
195207};
196208
197209namespace {
@@ -206,7 +218,7 @@ PyObject _CPyCppyy_DefaultStruct = {
206218 1 , &PyDefault_t_Type
207219};
208220
209- // TOOD : refactor with Converters.cxx
221+ // TODO : refactor with Converters.cxx
210222struct CPyCppyy_tagCDataObject { // non-public (but stable)
211223 PyObject_HEAD
212224 char * b_ptr;
@@ -409,8 +421,9 @@ static PyObject* SetCppLazyLookup(PyObject*, PyObject* args)
409421 CPYCPPYY_GET_DICT_LOOKUP (dict) = CPyCppyyLookDictString;
410422#else
411423// As of py3.11, there is no longer a lookup function pointer in the dict object
412- // to replace. Since this feature is not widely advertised, it's simply droped
424+ // to replace. Since this feature is not widely advertised, it's simply dropped
413425 PyErr_Warn (PyExc_RuntimeWarning, (char *)" lazy lookup is no longer supported" );
426+ (void )args; // avoid warning about unused parameter
414427#endif
415428
416429 Py_RETURN_NONE;
@@ -489,7 +502,7 @@ static void* GetCPPInstanceAddress(const char* fname, PyObject* args, PyObject*
489502 return &((CPPInstance*)pyobj)->GetObjectRaw ();
490503
491504 } else if (CPyCppyy_PyText_Check (pyobj)) {
492- // special cases for acces to the CPyCppyy API
505+ // special cases for access to the CPyCppyy API
493506 std::string req = CPyCppyy_PyText_AsString ((PyObject*)pyobj);
494507 if (req == " Instance_AsVoidPtr" )
495508 return (void *)&Instance_AsVoidPtr;
@@ -528,8 +541,8 @@ static PyObject* addressof(PyObject* /* dummy */, PyObject* args, PyObject* kwds
528541 return nullptr ;
529542 }
530543
531- Cppyy::TCppFuncAddr_t addr = methods[0 ]->GetFunctionAddress ();
532- return PyLong_FromLongLong ((intptr_t )addr );
544+ Cppyy::TCppFuncAddr_t caddr = methods[0 ]->GetFunctionAddress ();
545+ return PyLong_FromLongLong ((intptr_t )caddr );
533546 }
534547
535548 // C functions (incl. ourselves)
@@ -568,7 +581,7 @@ static PyObject* AsCObject(PyObject* /* unused */, PyObject* args, PyObject* kwd
568581}
569582
570583// ----------------------------------------------------------------------------
571- static PyObject* AsCapsule (PyObject* /* dummy */ , PyObject* args, PyObject* kwds)
584+ static PyObject* AsCapsule (PyObject* /* unused */ , PyObject* args, PyObject* kwds)
572585{
573586// Return object proxy as an opaque PyCapsule.
574587 void * addr = GetCPPInstanceAddress (" as_capsule" , args, kwds);
@@ -582,7 +595,7 @@ static PyObject* AsCapsule(PyObject* /* dummy */, PyObject* args, PyObject* kwds
582595}
583596
584597// ----------------------------------------------------------------------------
585- static PyObject* AsCTypes (PyObject* /* dummy */ , PyObject* args, PyObject* kwds)
598+ static PyObject* AsCTypes (PyObject* /* unused */ , PyObject* args, PyObject* kwds)
586599{
587600// Return object proxy as a ctypes c_void_p
588601 void * addr = GetCPPInstanceAddress (" as_ctypes" , args, kwds);
@@ -607,6 +620,43 @@ static PyObject* AsCTypes(PyObject* /* dummy */, PyObject* args, PyObject* kwds)
607620 return ref;
608621}
609622
623+ // ----------------------------------------------------------------------------
624+ static PyObject* AsMemoryView (PyObject* /* unused */ , PyObject* pyobject)
625+ {
626+ // Return a raw memory view on arrays of PODs.
627+ if (!CPPInstance_Check (pyobject)) {
628+ PyErr_SetString (PyExc_TypeError, " C++ object proxy expected" );
629+ return nullptr ;
630+ }
631+
632+ CPPInstance* pyobj = (CPPInstance*)pyobject;
633+ Cppyy::TCppType_t klass = ((CPPClass*)Py_TYPE (pyobject))->fCppType ;
634+
635+ Py_ssize_t array_len = pyobj->ArrayLength ();
636+
637+ if (array_len < 0 || !Cppyy::IsAggregate (klass)) {
638+ PyErr_SetString (
639+ PyExc_TypeError, " object is not a proxy to an array of PODs of known size" );
640+ return nullptr ;
641+ }
642+
643+ Py_buffer view;
644+
645+ view.obj = pyobject;
646+ view.buf = pyobj->GetObject ();
647+ view.itemsize = Cppyy::SizeOf (klass);
648+ view.len = view.itemsize * array_len;
649+ view.readonly = 0 ;
650+ view.format = NULL ; // i.e. "B" assumed
651+ view.ndim = 1 ;
652+ view.shape = NULL ;
653+ view.strides = NULL ;
654+ view.suboffsets = NULL ;
655+ view.internal = NULL ;
656+
657+ return PyMemoryView_FromBuffer (&view);
658+ }
659+
610660// ----------------------------------------------------------------------------
611661static PyObject* BindObject (PyObject*, PyObject* args, PyObject* kwds)
612662{
@@ -850,9 +900,11 @@ static PyObject* SetMemoryPolicy(PyObject*, PyObject* args)
850900 if (!PyArg_ParseTuple (args, const_cast <char *>(" O!" ), &PyInt_Type, &policy))
851901 return nullptr ;
852902
903+ long old = (long )CallContext::sMemoryPolicy ;
904+
853905 long l = PyInt_AS_LONG (policy);
854906 if (CallContext::SetMemoryPolicy ((CallContext::ECallFlags)l)) {
855- Py_RETURN_NONE ;
907+ return PyInt_FromLong (old) ;
856908 }
857909
858910 PyErr_Format (PyExc_ValueError, " Unknown policy %ld" , l);
@@ -946,6 +998,8 @@ static PyMethodDef gCPyCppyyMethods[] = {
946998 METH_VARARGS | METH_KEYWORDS, (char *)" Retrieve address of proxied object or field in a PyCapsule." },
947999 {(char *) " as_ctypes" , (PyCFunction)AsCTypes,
9481000 METH_VARARGS | METH_KEYWORDS, (char *)" Retrieve address of proxied object or field in a ctypes c_void_p." },
1001+ {(char *) " as_memoryview" , (PyCFunction)AsMemoryView,
1002+ METH_O, (char *)" Represent an array of objects as raw memory." },
9491003 {(char *)" bind_object" , (PyCFunction)BindObject,
9501004 METH_VARARGS | METH_KEYWORDS, (char *) " Create an object of given type, from given address." },
9511005 {(char *) " move" , (PyCFunction)Move,
@@ -1027,7 +1081,7 @@ extern "C" void initlibcppyy()
10271081#endif
10281082
10291083#if PY_VERSION_HEX < 0x030b0000
1030- // prepare for lazyness (the insert is needed to capture the most generic lookup
1084+ // prepare for laziness (the insert is needed to capture the most generic lookup
10311085// function, just in case ...)
10321086 PyObject* dict = PyDict_New ();
10331087 PyObject* notstring = PyInt_FromLong (5 );
0 commit comments