From 7e90570bbd440f816691ab94e92de15b2ba65fc0 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Thu, 14 Mar 2013 01:15:43 +0000 Subject: [PATCH] Update to sip 4.14.4 git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@73655 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- build.py | 4 +- sip/siplib/apiversions.c | 2 +- sip/siplib/bool.cpp | 2 +- sip/siplib/descriptors.c | 2 +- sip/siplib/objmap.c | 2 +- sip/siplib/qtlib.c | 2 +- sip/siplib/sip.h | 21 +++-- sip/siplib/sipint.h | 5 +- sip/siplib/siplib.c | 83 ++++++++++++----- sip/siplib/threads.c | 189 +++++++++++++++++++++------------------ sip/siplib/voidptr.c | 58 ++++++------ 11 files changed, 217 insertions(+), 153 deletions(-) diff --git a/build.py b/build.py index befe016e..35a2a884 100755 --- a/build.py +++ b/build.py @@ -54,9 +54,9 @@ isDarwin = sys.platform == "darwin" # Some tools will be downloaded for the builds. These are the versions and # MD5s of the tool binaries currently in use. -sipCurrentVersion = '4.14.1' +sipCurrentVersion = '4.14.4' sipMD5 = { - 'darwin' : '40854cc412e486909a289c1ffcd4e633', + 'darwin' : 'dd8d1128fc43586072206038bfa35a66', 'win32' : 'acfd4033565c754895e658b9fa993a56', 'linux' : '11fe8b21434d67b024ef204351877e79', } diff --git a/sip/siplib/apiversions.c b/sip/siplib/apiversions.c index b7b193ef..36b4b98e 100644 --- a/sip/siplib/apiversions.c +++ b/sip/siplib/apiversions.c @@ -1,7 +1,7 @@ /* * The implementation of the supprt for setting API versions. * - * Copyright (c) 2012 Riverbank Computing Limited + * Copyright (c) 2013 Riverbank Computing Limited * * This file is part of SIP. * diff --git a/sip/siplib/bool.cpp b/sip/siplib/bool.cpp index 6dc8f88e..d2849973 100644 --- a/sip/siplib/bool.cpp +++ b/sip/siplib/bool.cpp @@ -1,6 +1,6 @@ // This contains all the C++ code that is needed by the sip module. // -// Copyright (c) 2012 Riverbank Computing Limited +// Copyright (c) 2013 Riverbank Computing Limited // // This file is part of SIP. // diff --git a/sip/siplib/descriptors.c b/sip/siplib/descriptors.c index 81a59a1c..6f242a16 100644 --- a/sip/siplib/descriptors.c +++ b/sip/siplib/descriptors.c @@ -1,7 +1,7 @@ /* * The implementation of the different descriptors. * - * Copyright (c) 2012 Riverbank Computing Limited + * Copyright (c) 2013 Riverbank Computing Limited * * This file is part of SIP. * diff --git a/sip/siplib/objmap.c b/sip/siplib/objmap.c index 100bd952..c65e9ab0 100644 --- a/sip/siplib/objmap.c +++ b/sip/siplib/objmap.c @@ -2,7 +2,7 @@ * This module implements a hash table class for mapping C/C++ addresses to the * corresponding wrapped Python object. * - * Copyright (c) 2012 Riverbank Computing Limited + * Copyright (c) 2013 Riverbank Computing Limited * * This file is part of SIP. * diff --git a/sip/siplib/qtlib.c b/sip/siplib/qtlib.c index 1ffb6234..3b637fa4 100644 --- a/sip/siplib/qtlib.c +++ b/sip/siplib/qtlib.c @@ -2,7 +2,7 @@ * The SIP library code that implements the interface to the optional module * supplied Qt support. * - * Copyright (c) 2012 Riverbank Computing Limited + * Copyright (c) 2013 Riverbank Computing Limited * * This file is part of SIP. * diff --git a/sip/siplib/sip.h b/sip/siplib/sip.h index 54f75d9f..b9cec556 100644 --- a/sip/siplib/sip.h +++ b/sip/siplib/sip.h @@ -1,7 +1,7 @@ /* * The SIP module interface. * - * Copyright (c) 2012 Riverbank Computing Limited + * Copyright (c) 2013 Riverbank Computing Limited * * This file is part of SIP. * @@ -54,8 +54,8 @@ extern "C" { /* * Define the SIP version number. */ -#define SIP_VERSION 0x040e01 -#define SIP_VERSION_STR "4.14.1" +#define SIP_VERSION 0x040e04 +#define SIP_VERSION_STR "4.14.4" /* @@ -68,6 +68,11 @@ extern "C" { * * History: * + * 9.2 Added sip_gilstate_t and SIP_RELEASE_GIL to the public API. + * Renamed sip_api_call_error_handler() to + * sip_api_call_error_handler_old(). + * Added the new sip_api_call_error_handler() to the private API. + * * 9.1 Added the capsule type. * Added the 'z' format character to sip_api_build_result(). * Added the 'z', '!' and '$' format characters to @@ -186,7 +191,7 @@ extern "C" { * 0.0 Original version. */ #define SIP_API_MAJOR_NR 9 -#define SIP_API_MINOR_NR 1 +#define SIP_API_MINOR_NR 2 /* The name of the sip module. */ @@ -343,7 +348,9 @@ typedef void *(*sipCastFunc)(void *, const struct _sipTypeDef *); typedef const struct _sipTypeDef *(*sipSubClassConvertFunc)(void **); typedef int (*sipConvertToFunc)(PyObject *, void **, int *, PyObject *); typedef PyObject *(*sipConvertFromFunc)(void *, PyObject *); -typedef void (*sipVirtErrorHandlerFunc)(struct _sipSimpleWrapper *); +typedef void (*sipVirtErrorHandlerFunc)(struct _sipSimpleWrapper *, + sip_gilstate_t); +typedef void (*sipVirtErrorHandlerFuncOld)(struct _sipSimpleWrapper *); typedef int (*sipVirtHandlerFunc)(sip_gilstate_t, sipVirtErrorHandlerFunc, struct _sipSimpleWrapper *, PyObject *, ...); typedef void (*sipAssignFunc)(void *, SIP_SSIZE_T, const void *); @@ -1454,8 +1461,10 @@ typedef struct _sipAPIDef { int (*api_parse_result_ex)(sip_gilstate_t, sipVirtErrorHandlerFunc, sipSimpleWrapper *, PyObject *method, PyObject *res, const char *fmt, ...); - void (*api_call_error_handler)(sipVirtErrorHandlerFunc, + void (*api_call_error_handler_old)(sipVirtErrorHandlerFuncOld, sipSimpleWrapper *); + void (*api_call_error_handler)(sipVirtErrorHandlerFunc, + sipSimpleWrapper *, sip_gilstate_t); } sipAPIDef; diff --git a/sip/siplib/sipint.h b/sip/siplib/sipint.h index a97a44c1..05bcf229 100644 --- a/sip/siplib/sipint.h +++ b/sip/siplib/sipint.h @@ -1,7 +1,7 @@ /* * This file defines the SIP library internal interfaces. * - * Copyright (c) 2012 Riverbank Computing Limited + * Copyright (c) 2013 Riverbank Computing Limited * * This file is part of SIP. * @@ -127,7 +127,8 @@ int sip_api_save_slot(sipSlot *sp, PyObject *rxObj, const char *slot); sipClassTypeDef *sipGetGeneratedClassType(sipEncodedTypeDef *enc, const sipClassTypeDef *ctd); void sipSaveMethod(sipPyMethod *pm,PyObject *meth); -void *sipGetPending(sipWrapper **op, int *fp); +int sipGetPending(void **pp, sipWrapper **op, int *fp); +int sipIsPending(); PyObject *sipWrapSimpleInstance(void *cppPtr, const sipTypeDef *td, sipWrapper *owner, int initflags); void *sipConvertRxEx(sipWrapper *txSelf, const char *sigargs, diff --git a/sip/siplib/siplib.c b/sip/siplib/siplib.c index 64d3d799..2cd1b75b 100644 --- a/sip/siplib/siplib.c +++ b/sip/siplib/siplib.c @@ -1,7 +1,7 @@ /* * SIP library code. * - * Copyright (c) 2012 Riverbank Computing Limited + * Copyright (c) 2013 Riverbank Computing Limited * * This file is part of SIP. * @@ -185,7 +185,9 @@ static int sip_api_parse_result_ex(sip_gilstate_t gil_state, static int sip_api_parse_result(int *isErr, PyObject *method, PyObject *res, const char *fmt, ...); static void sip_api_call_error_handler(sipVirtErrorHandlerFunc error_handler, - sipSimpleWrapper *py_self); + sipSimpleWrapper *py_self, sip_gilstate_t gil_state); +static void sip_api_call_error_handler_old( + sipVirtErrorHandlerFuncOld error_handler, sipSimpleWrapper *py_self); static void sip_api_trace(unsigned mask,const char *fmt,...); static void sip_api_transfer_back(PyObject *self); static void sip_api_transfer_to(PyObject *self, PyObject *owner); @@ -370,6 +372,7 @@ static const sipAPIDef sip_api = { sip_api_parse_kwd_args, sip_api_add_exception, sip_api_parse_result_ex, + sip_api_call_error_handler_old, sip_api_call_error_handler }; @@ -527,6 +530,7 @@ static sipSymbol *sipSymbolList = NULL; /* The list of published symbols. */ static sipAttrGetter *sipAttrGetters = NULL; /* The list of attribute getters. */ static sipPyObject *sipRegisteredPyTypes = NULL; /* Registered Python types. */ static PyInterpreterState *sipInterpreter = NULL; /* The interpreter. */ +static int destroy_on_exit = TRUE; /* Destroy owned objects on exit. */ static void addClassSlots(sipWrapperType *wt, sipClassTypeDef *ctd); @@ -620,6 +624,7 @@ static PyObject *wrapInstance(PyObject *self, PyObject *args); static PyObject *unwrapInstance(PyObject *self, PyObject *args); static PyObject *transferBack(PyObject *self, PyObject *args); static PyObject *transferTo(PyObject *self, PyObject *args); +static PyObject *setDestroyOnExit(PyObject *self, PyObject *args); static void print_object(const char *label, PyObject *obj); static void addToParent(sipWrapper *self, sipWrapper *owner); static void removeFromParent(sipWrapper *self); @@ -705,6 +710,7 @@ PyMODINIT_FUNC SIP_MODULE_ENTRY(void) {"ispyowned", isPyOwned, METH_VARARGS, NULL}, {"setapi", sipSetAPI, METH_VARARGS, NULL}, {"setdeleted", setDeleted, METH_VARARGS, NULL}, + {"setdestroyonexit", setDestroyOnExit, METH_VARARGS, NULL}, {"settracemask", setTraceMask, METH_VARARGS, NULL}, {"transferback", transferBack, METH_VARARGS, NULL}, {"transferto", transferTo, METH_VARARGS, NULL}, @@ -1222,6 +1228,21 @@ static PyObject *wrapInstance(PyObject *self, PyObject *args) } +/* + * Set the destroy on exit flag. + */ +static PyObject *setDestroyOnExit(PyObject *self, PyObject *args) +{ + if (PyArg_ParseTuple(args, "i:setdestroyonexit", &destroy_on_exit)) + { + Py_INCREF(Py_None); + return Py_None; + } + + return NULL; +} + + /* * Register a client module. A negative value is returned and an exception * raised if there was an error. @@ -2229,20 +2250,38 @@ static int sip_api_parse_result_ex(sip_gilstate_t gil_state, Py_DECREF(method); - SIP_RELEASE_GIL(gil_state); - if (rc < 0) - sip_api_call_error_handler(error_handler, py_self); + sip_api_call_error_handler(error_handler, py_self, gil_state); + + SIP_RELEASE_GIL(gil_state); return rc; } /* - * Call a virtual error handler. + * Call a virtual error handler. This is called with the GIL and from the + * thread that raised the error. */ static void sip_api_call_error_handler(sipVirtErrorHandlerFunc error_handler, - sipSimpleWrapper *py_self) + sipSimpleWrapper *py_self, sip_gilstate_t sipGILState) +{ + if (error_handler != NULL) + error_handler(py_self, sipGILState); + else + PyErr_Print(); +} + + +/* + * Call a virtual error handler. This is called without the GIL. This is + * deprecated. + */ +#if SIP_API_MAJOR_NR != 9 +#error Remove deprecated error handler support. +#endif +static void sip_api_call_error_handler_old( + sipVirtErrorHandlerFuncOld error_handler, sipSimpleWrapper *py_self) { if (error_handler != NULL) { @@ -2251,6 +2290,10 @@ static void sip_api_call_error_handler(sipVirtErrorHandlerFunc error_handler, else { SIP_BLOCK_THREADS + /* + * The current thread may not be the one that raised the exception and + * so may not print anything. This is why this function is deprecated. + */ PyErr_Print(); SIP_UNBLOCK_THREADS } @@ -9245,7 +9288,7 @@ static PyObject *sipSimpleWrapper_new(sipWrapperType *wt, PyObject *args, /* * See if the object is being created explicitly rather than being wrapped. */ - if (sipGetPending(NULL, NULL) == NULL) + if (!sipIsPending()) { /* * See if it cannot be instantiated or sub-classed from Python, eg. @@ -9314,7 +9357,10 @@ static int sipSimpleWrapper_init(sipSimpleWrapper *self, PyObject *args, unused = NULL; /* Check there is no existing C++ instance waiting to be wrapped. */ - if ((sipNew = sipGetPending(&owner, &sipFlags)) == NULL) + if (sipGetPending(&sipNew, &owner, &sipFlags) < 0) + return -1; + + if (sipNew == NULL) { PyObject *parseErr = NULL; @@ -9915,17 +9961,7 @@ static int sipWrapper_clear(sipWrapper *self) /* Detach children (which will be owned by C/C++). */ while ((sw = (sipSimpleWrapper *)self->first_child) != NULL) - { - /* - * Although this object is being garbage collected it doesn't follow - * that it's children should be. So we make sure that the child stays - * alive and remember we have done so. - */ - Py_INCREF(sw); - sipSetCppHasRef(sw); - removeFromParent(self->first_child); - } return vret; } @@ -10364,8 +10400,6 @@ static void addTypeSlots(PyHeapTypeObject *heap_to, sipPySlotDef *slots) */ static void forgetObject(sipSimpleWrapper *sw) { - const sipClassTypeDef *ctd; - /* * This is needed because we release the GIL when calling a C++ dtor. * Without it the cyclic garbage collector can be invoked from another @@ -10385,10 +10419,11 @@ static void forgetObject(sipSimpleWrapper *sw) */ sipOMRemoveObject(&cppPyMap, sw); - if (getPtrTypeDef(sw, &ctd) != NULL) + if (sipInterpreter != NULL || destroy_on_exit) { - /* Call the C++ dtor if there is one. */ - if (ctd->ctd_dealloc != NULL) + const sipClassTypeDef *ctd; + + if (getPtrTypeDef(sw, &ctd) != NULL && ctd->ctd_dealloc != NULL) ctd->ctd_dealloc(sw); } diff --git a/sip/siplib/threads.c b/sip/siplib/threads.c index 3305f508..992e3fc3 100644 --- a/sip/siplib/threads.c +++ b/sip/siplib/threads.c @@ -3,7 +3,7 @@ * C++ classes that provide a thread interface to interact properly with the * Python threading infrastructure. * - * Copyright (c) 2012 Riverbank Computing Limited + * Copyright (c) 2013 Riverbank Computing Limited * * This file is part of SIP. * @@ -47,46 +47,45 @@ typedef struct _threadDef { struct _threadDef *next; /* Next in the list. */ } threadDef; - static threadDef *threads = NULL; /* Linked list of threads. */ - -static threadDef *currentThreadDef(void); +static threadDef *currentThreadDef(int auto_alloc); #endif -static pendingDef pending; /* An object waiting to be wrapped. */ +static pendingDef *get_pending(int auto_alloc); /* - * Get the address of any C/C++ object waiting to be wrapped. + * Get the address etc. of any C/C++ object waiting to be wrapped. */ -void *sipGetPending(sipWrapper **op, int *fp) +int sipGetPending(void **pp, sipWrapper **op, int *fp) { - pendingDef *pp; + pendingDef *pd; -#ifdef WITH_THREAD - threadDef *thread; + if ((pd = get_pending(TRUE)) == NULL) + return -1; - if ((thread = currentThreadDef()) != NULL) - pp = &thread->pending; - else - pp = &pending; -#else - pp = &pending; -#endif + *pp = pd->cpp; + *op = pd->owner; + *fp = pd->flags; - if (pp->cpp != NULL) - { - if (op != NULL) - *op = pp->owner; + return 0; +} - if (fp != NULL) - *fp = pp->flags; - } - return pp->cpp; +/* + * Return TRUE if anything is pending. + */ +int sipIsPending() +{ + pendingDef *pd; + + if ((pd = get_pending(FALSE)) == NULL) + return FALSE; + + return (pd->cpp != NULL); } @@ -98,11 +97,8 @@ PyObject *sipWrapSimpleInstance(void *cppPtr, const sipTypeDef *td, { static PyObject *nullargs = NULL; - pendingDef old_pending; + pendingDef old_pending, *pd; PyObject *self; -#ifdef WITH_THREAD - threadDef *thread; -#endif if (nullargs == NULL && (nullargs = PyTuple_New(0)) == NULL) return NULL; @@ -119,41 +115,18 @@ PyObject *sipWrapSimpleInstance(void *cppPtr, const sipTypeDef *td, * recursively. Therefore we save any existing pending object before * setting the new one. */ -#ifdef WITH_THREAD - if ((thread = currentThreadDef()) != NULL) - { - old_pending = thread->pending; + if ((pd = get_pending(TRUE)) == NULL) + return NULL; - thread->pending.cpp = cppPtr; - thread->pending.owner = owner; - thread->pending.flags = flags; - } - else - { - old_pending = pending; + old_pending = *pd; - pending.cpp = cppPtr; - pending.owner = owner; - pending.flags = flags; - } -#else - old_pending = pending; - - pending.cpp = cppPtr; - pending.owner = owner; - pending.flags = flags; -#endif + pd->cpp = cppPtr; + pd->owner = owner; + pd->flags = flags; self = PyObject_Call((PyObject *)sipTypeAsPyTypeObject(td), nullargs, NULL); -#ifdef WITH_THREAD - if (thread != NULL) - thread->pending = old_pending; - else - pending = old_pending; -#else - pending = old_pending; -#endif + *pd = old_pending; return self; } @@ -163,44 +136,52 @@ PyObject *sipWrapSimpleInstance(void *cppPtr, const sipTypeDef *td, * This is called from a newly created thread to initialise some thread local * storage. */ +#if SIP_API_MAJOR_NR != 9 +#error Remove deprecated sip_api_start_thread(). +#endif void sip_api_start_thread(void) { -#ifdef WITH_THREAD - threadDef *thread; - - /* Save the thread ID. First, find an empty slot in the list. */ - for (thread = threads; thread != NULL; thread = thread->next) - if (thread->thr_ident == 0) - break; - - if (thread == NULL) - { - thread = sip_api_malloc(sizeof (threadDef)); - thread->next = threads; - threads = thread; - } - - if (thread != NULL) - { - thread->thr_ident = PyThread_get_thread_ident(); - thread->pending.cpp = NULL; - } -#endif + /* + * The thread local storage allocation now happens when it is needed, so + * this is now redundant. + */ } /* - * Handle the termination of a thread. The thread state should already have - * been handled by the last call to PyGILState_Release(). + * Handle the termination of a thread. */ void sip_api_end_thread(void) { #ifdef WITH_THREAD threadDef *thread; + PyGILState_STATE gil = PyGILState_Ensure(); - /* We have the GIL at this point. */ - if ((thread = currentThreadDef()) != NULL) + if ((thread = currentThreadDef(FALSE)) != NULL) thread->thr_ident = 0; + + PyGILState_Release(gil); +#endif +} + + +/* + * Return the pending data for the current thread, allocating it if necessary, + * or NULL if there was an error. + */ +static pendingDef *get_pending(int auto_alloc) +{ +#ifdef WITH_THREAD + threadDef *thread; + + if ((thread = currentThreadDef(auto_alloc)) == NULL) + return NULL; + + return &thread->pending; +#else + static pendingDef pending; + + return &pending; #endif } @@ -208,17 +189,47 @@ void sip_api_end_thread(void) #ifdef WITH_THREAD /* - * Return the thread data for the current thread or NULL if it wasn't - * recognised. + * Return the thread data for the current thread, allocating it if necessary, + * or NULL if there was an error. */ -static threadDef *currentThreadDef(void) +static threadDef *currentThreadDef(int auto_alloc) { - threadDef *thread; + threadDef *thread, *empty = NULL; long ident = PyThread_get_thread_ident(); + /* See if we already know about the thread. */ for (thread = threads; thread != NULL; thread = thread->next) + { if (thread->thr_ident == ident) - break; + return thread; + + if (thread->thr_ident == 0) + empty = thread; + } + + if (!auto_alloc) + { + /* This is not an error. */ + return NULL; + } + + if (empty != NULL) + { + /* Use an empty entry in the list. */ + thread = empty; + } + else if ((thread = sip_api_malloc(sizeof (threadDef))) == NULL) + { + return NULL; + } + else + { + thread->next = threads; + threads = thread; + } + + thread->thr_ident = ident; + thread->pending.cpp = NULL; return thread; } diff --git a/sip/siplib/voidptr.c b/sip/siplib/voidptr.c index 24140bab..5bb974ea 100644 --- a/sip/siplib/voidptr.c +++ b/sip/siplib/voidptr.c @@ -1,7 +1,7 @@ /* * SIP library code. * - * Copyright (c) 2012 Riverbank Computing Limited + * Copyright (c) 2013 Riverbank Computing Limited * * This file is part of SIP. * @@ -46,7 +46,7 @@ struct vp_values { static int check_size(PyObject *self); static int check_rw(PyObject *self); static int check_index(PyObject *self, SIP_SSIZE_T idx); -#if PY_VERSION_HEX < 0x02060000 +#if PY_VERSION_HEX < 0x02060300 static SIP_SSIZE_T get_value_data(PyObject *value, void **value_ptr); #endif #if PY_VERSION_HEX < 0x02050000 @@ -455,7 +455,7 @@ static int sipVoidPtr_ass_subscript(PyObject *self, PyObject *key, { sipVoidPtrObject *v; Py_ssize_t start, size; -#if PY_VERSION_HEX >= 0x02060000 +#if PY_VERSION_HEX >= 0x02060300 Py_buffer value_view; #else Py_ssize_t value_size; @@ -502,7 +502,7 @@ static int sipVoidPtr_ass_subscript(PyObject *self, PyObject *key, return -1; } -#if PY_VERSION_HEX >= 0x02060000 +#if PY_VERSION_HEX >= 0x02060300 if (PyObject_GetBuffer(value, &value_view, PyBUF_CONTIG_RO) < 0) return -1; @@ -548,9 +548,9 @@ static PyMappingMethods sipVoidPtr_MappingMethods = { #endif -#if PY_VERSION_HEX >= 0x02060000 +#if PY_VERSION_HEX >= 0x02060300 /* - * The buffer implementation for Python v2.6 and later. + * The buffer implementation for Python v2.6.3 and later. */ static int sipVoidPtr_getbuffer(PyObject *self, Py_buffer *buf, int flags) { @@ -639,7 +639,7 @@ static PyBufferProcs sipVoidPtr_BufferProcs = { sipVoidPtr_getsegcount, /* bf_getsegcount */ #if PY_VERSION_HEX >= 0x02050000 (charbufferproc)sipVoidPtr_getreadbuffer, /* bf_getcharbuffer */ -#if PY_VERSION_HEX >= 0x02060000 +#if PY_VERSION_HEX >= 0x02060300 sipVoidPtr_getbuffer, /* bf_getbuffer */ 0 /* bf_releasebuffer */ #endif @@ -749,27 +749,16 @@ PyTypeObject sipVoidPtr_Type = { */ void *sip_api_convert_to_void_ptr(PyObject *obj) { + struct vp_values vp; + if (obj == NULL) { PyErr_SetString(PyExc_TypeError, "sip.voidptr is NULL"); return NULL; } - if (obj == Py_None) - return NULL; - - if (PyObject_TypeCheck(obj, &sipVoidPtr_Type)) - return ((sipVoidPtrObject *)obj)->voidptr; - -#if defined(SIP_USE_PYCAPSULE) - if (PyCapsule_CheckExact(obj)) - return PyCapsule_GetPointer(obj, NULL); -#endif - -#if defined(SIP_SUPPORT_PYCOBJECT) - if (PyCObject_Check(obj)) - return PyCObject_AsVoidPtr(obj); -#endif + if (vp_convertor(obj, &vp)) + return vp.voidptr; return PyLong_AsVoidPtr(obj); } @@ -857,7 +846,7 @@ static int check_index(PyObject *self, SIP_SSIZE_T idx) } -#if PY_VERSION_HEX < 0x02060000 +#if PY_VERSION_HEX < 0x02060300 /* * Get the address and size of the data from a value that supports the buffer * interface. @@ -986,6 +975,25 @@ static int vp_convertor(PyObject *arg, struct vp_values *vp) size = ((sipVoidPtrObject *)arg)->size; rw = ((sipVoidPtrObject *)arg)->rw; } +#if PY_VERSION_HEX >= 0x02060300 + else if (PyObject_CheckBuffer(arg)) + { + Py_buffer view; + + if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) < 0) + return 0; + + ptr = view.buf; + size = view.len; + rw = !view.readonly; + } +#endif +#if PY_VERSION_HEX < 0x03000000 + else if (PyObject_AsReadBuffer(arg, &ptr, &size) >= 0) + { + rw = (Py_TYPE(arg)->tp_as_buffer->bf_getwritebuffer != NULL); + } +#endif else { ptr = PyLong_AsVoidPtr(arg); @@ -993,9 +1001,9 @@ static int vp_convertor(PyObject *arg, struct vp_values *vp) if (PyErr_Occurred()) { #if PY_VERSION_HEX >= 0x03010000 - PyErr_SetString(PyExc_TypeError, "a single integer, CObject, None or another sip.voidptr object is required"); + PyErr_SetString(PyExc_TypeError, "a single integer, CObject, None, buffer protocol implementor or another sip.voidptr object is required"); #else - PyErr_SetString(PyExc_TypeError, "a single integer, Capsule, CObject, None or another sip.voidptr object is required"); + PyErr_SetString(PyExc_TypeError, "a single integer, Capsule, CObject, None, buffer protocol implementor or another sip.voidptr object is required"); #endif return 0; }