diff options
author | Larry Hastings <larry@hastings.org> | 2010-03-25 00:54:54 (GMT) |
---|---|---|
committer | Larry Hastings <larry@hastings.org> | 2010-03-25 00:54:54 (GMT) |
commit | 402b73fb8d54ec2b24b52fdd77d389d903fa6c44 (patch) | |
tree | ced928b7f7dce754142742e485ed8e836fbc9486 /Modules | |
parent | 53ff86ea5f0ed27f5eb5b966faf59dac298d6672 (diff) | |
download | cpython-402b73fb8d54ec2b24b52fdd77d389d903fa6c44.zip cpython-402b73fb8d54ec2b24b52fdd77d389d903fa6c44.tar.gz cpython-402b73fb8d54ec2b24b52fdd77d389d903fa6c44.tar.bz2 |
Backported PyCapsule from 3.1, and converted most uses of
CObject to PyCapsule.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ctypes/callproc.c | 23 | ||||
-rw-r--r-- | Modules/_ctypes/cfield.c | 7 | ||||
-rw-r--r-- | Modules/_ctypes/ctypes.h | 34 | ||||
-rw-r--r-- | Modules/_cursesmodule.c | 6 | ||||
-rw-r--r-- | Modules/_elementtree.c | 2 | ||||
-rw-r--r-- | Modules/_testcapimodule.c | 152 | ||||
-rw-r--r-- | Modules/cStringIO.c | 4 | ||||
-rw-r--r-- | Modules/cjkcodecs/cjkcodecs.h | 10 | ||||
-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 | 2 | ||||
-rw-r--r-- | Modules/socketmodule.h | 24 | ||||
-rw-r--r-- | Modules/unicodedata.c | 2 |
15 files changed, 240 insertions, 46 deletions
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index cf17e3a..8e0b6a0 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -83,6 +83,13 @@ #define DONT_USE_SEH #endif + +#define CTYPES_CAPSULE_ERROROBJ "_ctypes/callproc.c error object" +CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(CTYPES_CAPSULE_ERROROBJ) + +#define CTYPES_CAPSULE_WCHAR_T "_ctypes/callproc.c wchar_t buffer from unicode" +CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(CTYPES_CAPSULE_WCHAR_T) + /* 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 @@ -134,14 +141,22 @@ _ctypes_get_errobj(int **pspace) return NULL; } errobj = PyDict_GetItem(dict, error_object_name); - if (errobj) + if (errobj) { +#ifdef CTYPES_USING_CAPSULE + if (!PyCapsule_IsValid(errobj, CTYPES_CAPSULE_ERROROBJ)) { + PyErr_SetString(PyExc_RuntimeError, + "ctypes.error_object is an invalid capsule"); + return NULL; + } +#endif /* CTYPES_USING_CAPSULE */ Py_INCREF(errobj); + } else { void *space = PyMem_Malloc(sizeof(int) * 2); if (space == NULL) return NULL; memset(space, 0, sizeof(int) * 2); - errobj = PyCObject_FromVoidPtr(space, PyMem_Free); + errobj = CAPSULE_NEW(space, CTYPES_CAPSULE_ERROROBJ); if (errobj == NULL) return NULL; if (-1 == PyDict_SetItem(dict, error_object_name, @@ -150,7 +165,7 @@ _ctypes_get_errobj(int **pspace) return NULL; } } - *pspace = (int *)PyCObject_AsVoidPtr(errobj); + *pspace = (int *)CAPSULE_DEREFERENCE(errobj, CTYPES_CAPSULE_ERROROBJ); return errobj; } @@ -670,7 +685,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 = CAPSULE_NEW(pa->value.p, CTYPES_CAPSULE_WCHAR_T); if (!pa->keep) { PyMem_Free(pa->value.p); return -1; diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index bf247bc..d7fc5d2 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -10,6 +10,11 @@ #endif #include "ctypes.h" + +#define CTYPES_CAPSULE_WCHAR_T "_ctypes/cfield.c wchar_t buffer from unicode" +CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(CTYPES_CAPSULE_WCHAR_T) + + /******************************************************************/ /* PyCField_Type @@ -1457,7 +1462,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 = CAPSULE_NEW(buffer, CTYPES_CAPSULE_WCHAR_T); if (!keep) { Py_DECREF(value); PyMem_Free(buffer); diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 1003614..718ee52 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -445,6 +445,40 @@ PyObject *_ctypes_get_errobj(int **pspace); extern PyObject *ComError; #endif +#if PY_VERSION_HEX >= 0x020700A4 +/* Use PyCapsule for 2.7 */ + +#define CTYPES_USING_CAPSULE + +#define CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(name) \ +static void capsule_destructor_ ## name(PyObject *ptr) \ +{ \ + void *p = PyCapsule_GetPointer(ptr, name); \ + if (p) { \ + PyMem_Free(p); \ + } \ +} \ + +#define CAPSULE_NEW(pointer, name) \ + (PyCapsule_New(pointer, name, capsule_destructor_ ## name)) + +#define CAPSULE_DEREFERENCE(capsule, name) \ + (PyCapsule_GetPointer(capsule, name)) + +#else /* PY_VERSION_HEX >= 0x020700A4 */ +/* Use CObject for 2.6 and before */ + +#define CTYPES_CAPSULE_INSTANTIATE_DESTRUCTOR(name) + +#define CAPSULE_NEW(pointer, name) \ + (PyCObject_FromVoidPtr(pointer, PyMem_Free)) + +#define CAPSULE_DEREFERENCE(capsule, name) \ + (PyCObject_AsVoidPtr(capsule)) + +#endif /* PY_VERSION_HEX >= 0x020700A4 */ + + /* Local Variables: compile-command: "python setup.py -q build install --home ~" diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 430ab17..3f95cef 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -172,7 +172,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 * @@ -2745,8 +2745,8 @@ init_curses(void) return; 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 0aa1ebb..4311ba2 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -3059,7 +3059,7 @@ init_elementtree(void) #if defined(USE_PYEXPAT_CAPI) /* link against pyexpat, if possible */ - expat_capi = PyCObject_Import("pyexpat", "expat_CAPI"); + expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0); if (expat_capi) { /* check that it's usable */ if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 || diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 6bc6da2..023e62e 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1428,6 +1428,157 @@ test_string_from_format(PyObject *self, PyObject *args) #undef CHECK_1_FORMAT } +/* 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); + } + else + PyErr_Clear(); + } + + exit: + if (error) { + return raiseTestError("test_capsule", error); + } + Py_RETURN_NONE; +#undef FAIL +} + /* This is here to provide a docstring for test_descr. */ static PyObject * test_with_docstring(PyObject *self) @@ -1539,6 +1690,7 @@ static PyMethodDef TestMethods[] = { {"_test_thread_state", test_thread_state, METH_VARARGS}, {"_pending_threadfunc", pending_threadfunc, METH_VARARGS}, #endif + {"test_capsule", (PyCFunction)test_capsule, METH_NOARGS}, {"traceback_print", traceback_print, METH_VARARGS}, {"code_newempty", code_newempty, METH_VARARGS}, {"make_exception_with_doc", (PyCFunction)make_exception_with_doc, diff --git a/Modules/cStringIO.c b/Modules/cStringIO.c index 237d8c2..80588bf 100644 --- a/Modules/cStringIO.c +++ b/Modules/cStringIO.c @@ -761,8 +761,8 @@ initcStringIO(void) { Py_TYPE(&Otype)=&PyType_Type; if (PyType_Ready(&Otype) < 0) return; if (PyType_Ready(&Itype) < 0) return; - PyDict_SetItemString(d,"cStringIO_CAPI", - v = PyCObject_FromVoidPtr(&CAPI,NULL)); + v = PyCapsule_New(&CAPI, PycStringIO_CAPSULE_NAME, NULL); + PyDict_SetItemString(d,"cStringIO_CAPI", v); Py_XDECREF(v); /* Export Types */ diff --git a/Modules/cjkcodecs/cjkcodecs.h b/Modules/cjkcodecs/cjkcodecs.h index 4005bcf..236c3fe 100644 --- a/Modules/cjkcodecs/cjkcodecs.h +++ b/Modules/cjkcodecs/cjkcodecs.h @@ -282,7 +282,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; @@ -307,7 +307,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; } @@ -362,14 +362,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 5fb5ec0..794774b 100644 --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -1774,12 +1774,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 7b9e271..3f1eb57 100644 --- a/Modules/datetimemodule.c +++ b/Modules/datetimemodule.c @@ -4856,11 +4856,10 @@ initdatetime(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; - 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 47ef186..d428c66 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -2053,8 +2053,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); } diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index fbd0239..d44a691 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -4496,7 +4496,7 @@ init_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; diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h index ef8d0fc..48f230e 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 @@ -226,33 +227,18 @@ PySocketModule_APIObject PySocketModule; 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); + DPRINTF(" Loading capsule %s\n", PySocket_CAPSULE_NAME); + api = PyCapsule_Import(PySocket_CAPSULE_NAME, 1); 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; } diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index 552dae5..ede57cb 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -1261,7 +1261,7 @@ initunicodedata(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); } |