diff options
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ctypes/callproc.c | 16 | ||||
-rw-r--r-- | Modules/_ctypes/cfield.c | 14 | ||||
-rw-r--r-- | Modules/_cursesmodule.c | 7 | ||||
-rw-r--r-- | Modules/_elementtree.c | 2 | ||||
-rw-r--r-- | Modules/_ssl.c | 7 | ||||
-rw-r--r-- | Modules/_testcapimodule.c | 152 | ||||
-rw-r--r-- | Modules/cjkcodecs/cjkcodecs.h | 12 | ||||
-rw-r--r-- | Modules/cjkcodecs/multibytecodec.c | 4 | ||||
-rw-r--r-- | Modules/cjkcodecs/multibytecodec.h | 3 | ||||
-rw-r--r-- | Modules/datetimemodule.c | 9 | ||||
-rw-r--r-- | Modules/pyexpat.c | 4 | ||||
-rw-r--r-- | Modules/socketmodule.c | 10 | ||||
-rw-r--r-- | Modules/socketmodule.h | 45 | ||||
-rw-r--r-- | Modules/unicodedata.c | 2 |
14 files changed, 220 insertions, 67 deletions
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 3300cde..cbc5cf8 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -78,6 +78,16 @@ #define DONT_USE_SEH #endif +#define CTYPES_CAPSULE_NAME_PYMEM "_ctypes pymem" + +static void pymem_destructor(PyObject *ptr) +{ + void *p = PyCapsule_GetPointer(ptr, CTYPES_CAPSULE_NAME_PYMEM); + if (p) { + PyMem_Free(p); + } +} + /* ctypes maintains thread-local storage that has space for two error numbers: private copies of the system 'errno' value and, on Windows, the system error code @@ -136,7 +146,7 @@ _ctypes_get_errobj(int **pspace) if (space == NULL) return NULL; memset(space, 0, sizeof(int) * 2); - errobj = PyCObject_FromVoidPtr(space, PyMem_Free); + errobj = PyCapsule_New(space, CTYPES_CAPSULE_NAME_PYMEM, pymem_destructor); if (errobj == NULL) return NULL; if (-1 == PyDict_SetItem(dict, error_object_name, @@ -145,7 +155,7 @@ _ctypes_get_errobj(int **pspace) return NULL; } } - *pspace = (int *)PyCObject_AsVoidPtr(errobj); + *pspace = (int *)PyCapsule_GetPointer(errobj, CTYPES_CAPSULE_NAME_PYMEM); return errobj; } @@ -658,7 +668,7 @@ static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa) return -1; } memset(pa->value.p, 0, size); - pa->keep = PyCObject_FromVoidPtr(pa->value.p, PyMem_Free); + pa->keep = PyCapsule_New(pa->value.p, CTYPES_CAPSULE_NAME_PYMEM, pymem_destructor); if (!pa->keep) { PyMem_Free(pa->value.p); return -1; diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index ff24405..d7966a5 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -6,6 +6,18 @@ #endif #include "ctypes.h" + +#define CTYPES_CFIELD_CAPSULE_NAME_PYMEM "_ctypes/cfield.c pymem" + +static void pymem_destructor(PyObject *ptr) +{ + void *p = PyCapsule_GetPointer(ptr, CTYPES_CFIELD_CAPSULE_NAME_PYMEM); + if (p) { + PyMem_Free(p); + } +} + + /******************************************************************/ /* PyCField_Type @@ -1477,7 +1489,7 @@ Z_set(void *ptr, PyObject *value, Py_ssize_t size) return PyErr_NoMemory(); } memset(buffer, 0, size); - keep = PyCObject_FromVoidPtr(buffer, PyMem_Free); + keep = PyCapsule_New(buffer, CTYPES_CFIELD_CAPSULE_NAME_PYMEM, pymem_destructor); if (!keep) { Py_DECREF(value); PyMem_Free(buffer); diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 5cb198e..a92cc8e 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -104,6 +104,7 @@ char *PyCursesVersion = "2.2"; #include "Python.h" + #ifdef __osf__ #define STRICT_SYSV_CURSES /* Don't use ncurses extensions */ #endif @@ -174,7 +175,7 @@ static int initialisedcolors = FALSE; /* * Check the return code from a curses function and return None * or raise an exception as appropriate. These are exported using the - * CObject API. + * capsule API. */ static PyObject * @@ -2827,8 +2828,8 @@ PyInit__curses(void) return NULL; ModDict = d; /* For PyCurses_InitScr to use later */ - /* Add a CObject for the C API */ - c_api_object = PyCObject_FromVoidPtr((void *)PyCurses_API, NULL); + /* Add a capsule for the C API */ + c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, NULL); PyDict_SetItemString(d, "_C_API", c_api_object); Py_DECREF(c_api_object); diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index ac118b4..ae09893 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2809,7 +2809,7 @@ PyInit__elementtree(void) #if defined(USE_PYEXPAT_CAPI) /* link against pyexpat, if possible */ - capi = PyCObject_Import("pyexpat", "expat_CAPI"); + capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0); if (capi && strcmp(capi->magic, PyExpat_CAPI_MAGIC) == 0 && capi->size <= sizeof(*expat_capi) && diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 3c9dd61..b400057 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -71,6 +71,8 @@ enum py_ssl_version { /* Include symbols from _socket module */ #include "socketmodule.h" +static PySocketModule_APIObject PySocketModule; + #if defined(HAVE_POLL_H) #include <poll.h> #elif defined(HAVE_SYS_POLL_H) @@ -1626,6 +1628,7 @@ PyMODINIT_FUNC PyInit__ssl(void) { PyObject *m, *d; + PySocketModule_APIObject *socket_api; if (PyType_Ready(&PySSL_Type) < 0) return NULL; @@ -1636,8 +1639,10 @@ PyInit__ssl(void) d = PyModule_GetDict(m); /* Load _socket module and its C API */ - if (PySocketModule_ImportModuleAndAPI()) + socket_api = PySocketModule_ImportModuleAndAPI(); + if (!socket_api) return NULL; + PySocketModule = *socket_api; /* Init OpenSSL */ SSL_load_error_strings(); diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 3f7190c..f3899f5 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1102,6 +1102,155 @@ test_string_to_double(PyObject *self) { } +/* Coverage testing of capsule objects. */ + +static const char *capsule_name = "capsule name"; +static char *capsule_pointer = "capsule pointer"; +static char *capsule_context = "capsule context"; +static const char *capsule_error = NULL; +static int +capsule_destructor_call_count = 0; + +static void +capsule_destructor(PyObject *o) { + capsule_destructor_call_count++; + if (PyCapsule_GetContext(o) != capsule_context) { + capsule_error = "context did not match in destructor!"; + } else if (PyCapsule_GetDestructor(o) != capsule_destructor) { + capsule_error = "destructor did not match in destructor! (woah!)"; + } else if (PyCapsule_GetName(o) != capsule_name) { + capsule_error = "name did not match in destructor!"; + } else if (PyCapsule_GetPointer(o, capsule_name) != capsule_pointer) { + capsule_error = "pointer did not match in destructor!"; + } +} + +typedef struct { + char *name; + char *module; + char *attribute; +} known_capsule; + +static PyObject * +test_capsule(PyObject *self, PyObject *args) +{ + PyObject *object; + const char *error = NULL; + void *pointer; + void *pointer2; + known_capsule known_capsules[] = { + #define KNOWN_CAPSULE(module, name) { module "." name, module, name } + KNOWN_CAPSULE("_socket", "CAPI"), + KNOWN_CAPSULE("_curses", "_C_API"), + KNOWN_CAPSULE("datetime", "datetime_CAPI"), + { NULL, NULL }, + }; + known_capsule *known = &known_capsules[0]; + +#define FAIL(x) { error = (x); goto exit; } + +#define CHECK_DESTRUCTOR \ + if (capsule_error) { \ + FAIL(capsule_error); \ + } \ + else if (!capsule_destructor_call_count) { \ + FAIL("destructor not called!"); \ + } \ + capsule_destructor_call_count = 0; \ + + object = PyCapsule_New(capsule_pointer, capsule_name, capsule_destructor); + PyCapsule_SetContext(object, capsule_context); + capsule_destructor(object); + CHECK_DESTRUCTOR; + Py_DECREF(object); + CHECK_DESTRUCTOR; + + object = PyCapsule_New(known, "ignored", NULL); + PyCapsule_SetPointer(object, capsule_pointer); + PyCapsule_SetName(object, capsule_name); + PyCapsule_SetDestructor(object, capsule_destructor); + PyCapsule_SetContext(object, capsule_context); + capsule_destructor(object); + CHECK_DESTRUCTOR; + /* intentionally access using the wrong name */ + pointer2 = PyCapsule_GetPointer(object, "the wrong name"); + if (!PyErr_Occurred()) { + FAIL("PyCapsule_GetPointer should have failed but did not!"); + } + PyErr_Clear(); + if (pointer2) { + if (pointer2 == capsule_pointer) { + FAIL("PyCapsule_GetPointer should not have" + " returned the internal pointer!"); + } else { + FAIL("PyCapsule_GetPointer should have " + "returned NULL pointer but did not!"); + } + } + PyCapsule_SetDestructor(object, NULL); + Py_DECREF(object); + if (capsule_destructor_call_count) { + FAIL("destructor called when it should not have been!"); + } + + for (known = &known_capsules[0]; known->module != NULL; known++) { + /* yeah, ordinarily I wouldn't do this either, + but it's fine for this test harness. + */ + static char buffer[256]; +#undef FAIL +#define FAIL(x) \ + { \ + sprintf(buffer, "%s module: \"%s\" attribute: \"%s\"", \ + x, known->module, known->attribute); \ + error = buffer; \ + goto exit; \ + } \ + + PyObject *module = PyImport_ImportModule(known->module); + if (module) { + pointer = PyCapsule_Import(known->name, 0); + if (!pointer) { + Py_DECREF(module); + FAIL("PyCapsule_GetPointer returned NULL unexpectedly!"); + } + object = PyObject_GetAttrString(module, known->attribute); + if (!object) { + Py_DECREF(module); + return NULL; + } + pointer2 = PyCapsule_GetPointer(object, + "weebles wobble but they don't fall down"); + if (!PyErr_Occurred()) { + Py_DECREF(object); + Py_DECREF(module); + FAIL("PyCapsule_GetPointer should have failed but did not!"); + } + PyErr_Clear(); + if (pointer2) { + Py_DECREF(module); + Py_DECREF(object); + if (pointer2 == pointer) { + FAIL("PyCapsule_GetPointer should not have" + " returned its internal pointer!"); + } else { + FAIL("PyCapsule_GetPointer should have" + " returned NULL pointer but did not!"); + } + } + Py_DECREF(object); + Py_DECREF(module); + } + } + + exit: + if (error) { + return raiseTestError("test_capsule", error); + } + Py_RETURN_NONE; +#undef FAIL +} + #ifdef HAVE_GETTIMEOFDAY /* Profiling of integer performance */ static void print_delta(int test, struct timeval *s, struct timeval *e) @@ -1280,9 +1429,10 @@ static PyMethodDef TestMethods[] = { {"test_empty_argparse", (PyCFunction)test_empty_argparse,METH_NOARGS}, {"test_null_strings", (PyCFunction)test_null_strings, METH_NOARGS}, {"test_string_from_format", (PyCFunction)test_string_from_format, METH_NOARGS}, - {"test_string_to_double", (PyCFunction)test_string_to_double, METH_NOARGS}, {"test_with_docstring", (PyCFunction)test_with_docstring, METH_NOARGS, PyDoc_STR("This is a pretty normal docstring.")}, + {"test_string_to_double", (PyCFunction)test_string_to_double, METH_NOARGS}, + {"test_capsule", (PyCFunction)test_capsule, METH_NOARGS}, {"getargs_tuple", getargs_tuple, METH_VARARGS}, {"getargs_keywords", (PyCFunction)getargs_keywords, diff --git a/Modules/cjkcodecs/cjkcodecs.h b/Modules/cjkcodecs/cjkcodecs.h index 0530a33..e630671 100644 --- a/Modules/cjkcodecs/cjkcodecs.h +++ b/Modules/cjkcodecs/cjkcodecs.h @@ -239,6 +239,8 @@ static const struct dbcs_map *mapping_list; static const MultibyteCodec *codec_list = \ (const MultibyteCodec *)_codec_list; + + static PyObject * getmultibytecodec(void) { @@ -284,7 +286,7 @@ getcodec(PyObject *self, PyObject *encoding) return NULL; } - codecobj = PyCObject_FromVoidPtr((void *)codec, NULL); + codecobj = PyCapsule_New((void *)codec, PyMultibyteCodec_CAPSULE_NAME, NULL); if (codecobj == NULL) return NULL; @@ -309,7 +311,7 @@ register_maps(PyObject *module) int r; strcpy(mhname + sizeof("__map_") - 1, h->charset); r = PyModule_AddObject(module, mhname, - PyCObject_FromVoidPtr((void *)h, NULL)); + PyCapsule_New((void *)h, PyMultibyteCodec_CAPSULE_NAME, NULL)); if (r == -1) return -1; } @@ -364,14 +366,14 @@ importmap(const char *modname, const char *symbol, o = PyObject_GetAttrString(mod, (char*)symbol); if (o == NULL) goto errorexit; - else if (!PyCObject_Check(o)) { + else if (!PyCapsule_IsValid(o, PyMultibyteCodec_CAPSULE_NAME)) { PyErr_SetString(PyExc_ValueError, - "map data must be a CObject."); + "map data must be a Capsule."); goto errorexit; } else { struct dbcs_map *map; - map = PyCObject_AsVoidPtr(o); + map = PyCapsule_GetPointer(o, PyMultibyteCodec_CAPSULE_NAME); if (encmap != NULL) *encmap = map->encmap; if (decmap != NULL) diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c index c6b3492..1735dfd 100644 --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -1793,12 +1793,12 @@ __create_codec(PyObject *ignore, PyObject *arg) MultibyteCodecObject *self; MultibyteCodec *codec; - if (!PyCObject_Check(arg)) { + if (!PyCapsule_IsValid(arg, PyMultibyteCodec_CAPSULE_NAME)) { PyErr_SetString(PyExc_ValueError, "argument type invalid"); return NULL; } - codec = PyCObject_AsVoidPtr(arg); + codec = PyCapsule_GetPointer(arg, PyMultibyteCodec_CAPSULE_NAME); if (codec->codecinit != NULL && codec->codecinit(codec->config) != 0) return NULL; diff --git a/Modules/cjkcodecs/multibytecodec.h b/Modules/cjkcodecs/multibytecodec.h index 22ea5d4..71c02cc 100644 --- a/Modules/cjkcodecs/multibytecodec.h +++ b/Modules/cjkcodecs/multibytecodec.h @@ -132,6 +132,9 @@ typedef struct { #define MBENC_FLUSH 0x0001 /* encode all characters encodable */ #define MBENC_MAX MBENC_FLUSH +#define PyMultibyteCodec_CAPSULE_NAME "multibytecodec.__map_*" + + #ifdef __cplusplus } #endif diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c index 0c6e664..8ba3474 100644 --- a/Modules/datetimemodule.c +++ b/Modules/datetimemodule.c @@ -4792,11 +4792,10 @@ PyInit_datetime(void) Py_INCREF(&PyDateTime_TZInfoType); PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType); - x = PyCObject_FromVoidPtrAndDesc(&CAPI, (void*) DATETIME_API_MAGIC, - NULL); - if (x == NULL) - return NULL; - PyModule_AddObject(m, "datetime_CAPI", x); + x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL); + if (x == NULL) + return NULL; + PyModule_AddObject(m, "datetime_CAPI", x); /* A 4-year cycle has an extra leap day over what we'd get from * pasting together 4 single years. diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index a968e52..7a862c0 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -1987,8 +1987,8 @@ MODULE_INITFUNC(void) capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler; capi.SetUserData = XML_SetUserData; - /* export as cobject */ - capi_object = PyCObject_FromVoidPtr(&capi, NULL); + /* export using capsule */ + capi_object = PyCapsule_New(&capi, PyExpat_CAPSULE_NAME, NULL); if (capi_object) PyModule_AddObject(m, "expat_CAPI", capi_object); return m; diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index c229c07..6ec5220 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -4146,6 +4146,14 @@ PySocketModule_APIObject PySocketModuleAPI = NULL }; +PySocketModule_APIObject * +PySocketModule_ImportModuleAndAPI(void) +{ + void *api; + api = PyCapsule_Import(PySocket_CAPSULE_NAME, 1);; + return (PySocketModule_APIObject *)api; +} + /* Initialize the _socket module. @@ -4231,7 +4239,7 @@ PyInit__socket(void) /* Export C API */ if (PyModule_AddObject(m, PySocket_CAPI_NAME, - PyCObject_FromVoidPtr((void *)&PySocketModuleAPI, NULL) + PyCapsule_New(&PySocketModuleAPI, PySocket_CAPSULE_NAME, NULL) ) != 0) return NULL; diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h index 8d19cbf..a323409 100644 --- a/Modules/socketmodule.h +++ b/Modules/socketmodule.h @@ -78,6 +78,7 @@ extern "C" { /* Python module and C API name */ #define PySocket_MODULE_NAME "_socket" #define PySocket_CAPI_NAME "CAPI" +#define PySocket_CAPSULE_NAME PySocket_MODULE_NAME "." PySocket_CAPI_NAME /* Abstract the socket file descriptor type */ #ifdef MS_WINDOWS @@ -142,12 +143,12 @@ typedef struct { the _socket module. Since cross-DLL linking introduces a lot of problems on many platforms, the "trick" is to wrap the C API of a module in a struct which then gets exported to - other modules via a PyCObject. + other modules via a PyCapsule. The code in socketmodule.c defines this struct (which currently only contains the type object reference, but could very well also include other C APIs needed by other modules) - and exports it as PyCObject via the module dictionary + and exports it as PyCapsule via the module dictionary under the name "CAPI". Other modules can now include the socketmodule.h file @@ -212,49 +213,11 @@ typedef struct { ... */ -static -PySocketModule_APIObject PySocketModule; - /* You *must* call this before using any of the functions in PySocketModule and check its outcome; otherwise all accesses will result in a segfault. Returns 0 on success. */ -#ifndef DPRINTF -# define DPRINTF if (0) printf -#endif - -static -int PySocketModule_ImportModuleAndAPI(void) -{ - PyObject *mod = 0, *v = 0; - char *apimodule = PySocket_MODULE_NAME; - char *apiname = PySocket_CAPI_NAME; - void *api; - - DPRINTF("Importing the %s C API...\n", apimodule); - mod = PyImport_ImportModuleNoBlock(apimodule); - if (mod == NULL) - goto onError; - DPRINTF(" %s package found\n", apimodule); - v = PyObject_GetAttrString(mod, apiname); - if (v == NULL) - goto onError; - Py_DECREF(mod); - DPRINTF(" API object %s found\n", apiname); - api = PyCObject_AsVoidPtr(v); - if (api == NULL) - goto onError; - Py_DECREF(v); - memcpy(&PySocketModule, api, sizeof(PySocketModule)); - DPRINTF(" API object loaded and initialized.\n"); - return 0; - - onError: - DPRINTF(" not found.\n"); - Py_XDECREF(mod); - Py_XDECREF(v); - return -1; -} +PyAPI_FUNC(PySocketModule_APIObject *) PySocketModule_ImportModuleAndAPI(void); #endif /* !PySocket_BUILDING_SOCKET */ diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index 301cee7..2dddc48 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -1275,7 +1275,7 @@ PyInit_unicodedata(void) PyModule_AddObject(m, "ucd_3_2_0", v); /* Export C API */ - v = PyCObject_FromVoidPtr((void *) &hashAPI, NULL); + v = PyCapsule_New((void *)&hashAPI, PyUnicodeData_CAPSULE_NAME, NULL); if (v != NULL) PyModule_AddObject(m, "ucnhash_CAPI", v); return m; |