diff options
Diffstat (limited to 'Cython/Utility/CommonStructures.c')
-rw-r--r-- | Cython/Utility/CommonStructures.c | 170 |
1 files changed, 113 insertions, 57 deletions
diff --git a/Cython/Utility/CommonStructures.c b/Cython/Utility/CommonStructures.c index c7945feb4..f39f3d70d 100644 --- a/Cython/Utility/CommonStructures.c +++ b/Cython/Utility/CommonStructures.c @@ -1,43 +1,80 @@ +/////////////// FetchSharedCythonModule.proto /////// + +static PyObject *__Pyx_FetchSharedCythonABIModule(void); + +/////////////// FetchSharedCythonModule //////////// + +static PyObject *__Pyx_FetchSharedCythonABIModule(void) { + PyObject *abi_module = PyImport_AddModule((char*) __PYX_ABI_MODULE_NAME); + if (unlikely(!abi_module)) return NULL; + Py_INCREF(abi_module); + return abi_module; +} + /////////////// FetchCommonType.proto /////////////// +#if !CYTHON_USE_TYPE_SPECS static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type); +#else +static PyTypeObject* __Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases); +#endif /////////////// FetchCommonType /////////////// +//@requires:ExtensionTypes.c::FixUpExtensionType +//@requires: FetchSharedCythonModule +//@requires:StringTools.c::IncludeStringH + +static int __Pyx_VerifyCachedType(PyObject *cached_type, + const char *name, + Py_ssize_t basicsize, + Py_ssize_t expected_basicsize) { + if (!PyType_Check(cached_type)) { + PyErr_Format(PyExc_TypeError, + "Shared Cython type %.200s is not a type object", name); + return -1; + } + if (basicsize != expected_basicsize) { + PyErr_Format(PyExc_TypeError, + "Shared Cython type %.200s has the wrong size, try recompiling", + name); + return -1; + } + return 0; +} +#if !CYTHON_USE_TYPE_SPECS static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) { - PyObject* fake_module; - PyTypeObject* cached_type = NULL; - - fake_module = PyImport_AddModule((char*) "_cython_" CYTHON_ABI); - if (!fake_module) return NULL; - Py_INCREF(fake_module); - - cached_type = (PyTypeObject*) PyObject_GetAttrString(fake_module, type->tp_name); + PyObject* abi_module; + const char* object_name; + PyTypeObject *cached_type = NULL; + + abi_module = __Pyx_FetchSharedCythonABIModule(); + if (!abi_module) return NULL; + // get the final part of the object name (after the last dot) + object_name = strrchr(type->tp_name, '.'); + object_name = object_name ? object_name+1 : type->tp_name; + cached_type = (PyTypeObject*) PyObject_GetAttrString(abi_module, object_name); if (cached_type) { - if (!PyType_Check((PyObject*)cached_type)) { - PyErr_Format(PyExc_TypeError, - "Shared Cython type %.200s is not a type object", - type->tp_name); + if (__Pyx_VerifyCachedType( + (PyObject *)cached_type, + object_name, + cached_type->tp_basicsize, + type->tp_basicsize) < 0) { goto bad; } - if (cached_type->tp_basicsize != type->tp_basicsize) { - PyErr_Format(PyExc_TypeError, - "Shared Cython type %.200s has the wrong size, try recompiling", - type->tp_name); - goto bad; - } - } else { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad; - PyErr_Clear(); - if (PyType_Ready(type) < 0) goto bad; - if (PyObject_SetAttrString(fake_module, type->tp_name, (PyObject*) type) < 0) - goto bad; - Py_INCREF(type); - cached_type = type; + goto done; } + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad; + PyErr_Clear(); + if (PyType_Ready(type) < 0) goto bad; + if (PyObject_SetAttrString(abi_module, object_name, (PyObject *)type) < 0) + goto bad; + Py_INCREF(type); + cached_type = type; + done: - Py_DECREF(fake_module); + Py_DECREF(abi_module); // NOTE: always returns owned reference, or NULL on error return cached_type; @@ -46,41 +83,60 @@ bad: cached_type = NULL; goto done; } +#else +static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) { + PyObject *abi_module, *cached_type = NULL; + // get the final part of the object name (after the last dot) + const char* object_name = strrchr(spec->name, '.'); + object_name = object_name ? object_name+1 : spec->name; -/////////////// FetchCommonPointer.proto /////////////// - -static void* __Pyx_FetchCommonPointer(void* pointer, const char* name); - -/////////////// FetchCommonPointer /////////////// - - -static void* __Pyx_FetchCommonPointer(void* pointer, const char* name) { -#if PY_VERSION_HEX >= 0x02070000 - PyObject* fake_module = NULL; - PyObject* capsule = NULL; - void* value = NULL; - - fake_module = PyImport_AddModule((char*) "_cython_" CYTHON_ABI); - if (!fake_module) return NULL; - Py_INCREF(fake_module); + abi_module = __Pyx_FetchSharedCythonABIModule(); + if (!abi_module) return NULL; - capsule = PyObject_GetAttrString(fake_module, name); - if (!capsule) { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad; - PyErr_Clear(); - capsule = PyCapsule_New(pointer, name, NULL); - if (!capsule) goto bad; - if (PyObject_SetAttrString(fake_module, name, capsule) < 0) + cached_type = PyObject_GetAttrString(abi_module, object_name); + if (cached_type) { + Py_ssize_t basicsize; +#if CYTHON_COMPILING_IN_LIMITED_API + PyObject *py_basicsize; + py_basicsize = PyObject_GetAttrString(cached_type, "__basicsize__"); + if (unlikely(!py_basicsize)) goto bad; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = 0; + if (unlikely(basicsize == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; +#else + basicsize = likely(PyType_Check(cached_type)) ? ((PyTypeObject*) cached_type)->tp_basicsize : -1; +#endif + if (__Pyx_VerifyCachedType( + cached_type, + object_name, + basicsize, + spec->basicsize) < 0) { goto bad; + } + goto done; } - value = PyCapsule_GetPointer(capsule, name); + + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad; + PyErr_Clear(); + // We pass the ABI module reference to avoid keeping the user module alive by foreign type usages. + CYTHON_UNUSED_VAR(module); + cached_type = __Pyx_PyType_FromModuleAndSpec(abi_module, spec, bases); + if (unlikely(!cached_type)) goto bad; + if (unlikely(__Pyx_fix_up_extension_type_from_spec(spec, (PyTypeObject *) cached_type) < 0)) goto bad; + if (PyObject_SetAttrString(abi_module, object_name, cached_type) < 0) goto bad; + +done: + Py_DECREF(abi_module); + // NOTE: always returns owned reference, or NULL on error + assert(cached_type == NULL || PyType_Check(cached_type)); + return (PyTypeObject *) cached_type; bad: - Py_XDECREF(capsule); - Py_DECREF(fake_module); - return value; -#else - return pointer; -#endif + Py_XDECREF(cached_type); + cached_type = NULL; + goto done; } +#endif + |