Author: Armin Rigo <ar...@tunes.org> Branch: cffi-1.0 Changeset: r1966:897b96412b7a Date: 2015-05-11 11:15 +0200 http://bitbucket.org/cffi/cffi/changeset/897b96412b7a/
Log: Tweak tweak tweak: use an initialization sequence on CPython that is closer to the PyPy one. Should make future version checking more uniform in CPython and PyPy. diff --git a/_cffi1/_cffi_include.h b/_cffi1/_cffi_include.h --- a/_cffi1/_cffi_include.h +++ b/_cffi1/_cffi_include.h @@ -51,14 +51,6 @@ #ifndef PYPY_VERSION -#if PY_MAJOR_VERSION < 3 -# undef PyCapsule_CheckExact -# undef PyCapsule_GetPointer -# define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule)) -# define PyCapsule_GetPointer(capsule, name) \ - (PyCObject_AsVoidPtr(capsule)) -#endif - #if PY_MAJOR_VERSION >= 3 # define PyInt_FromLong PyLong_FromLong #endif @@ -143,10 +135,7 @@ ((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23]) #define _cffi_convert_array_from_object \ ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24]) -#define _cffi_init_module \ - ((PyObject *(*)(char *, const struct _cffi_type_context_s *)) \ - _cffi_exports[25]) -#define _CFFI_NUM_EXPORTS 26 +#define _CFFI_NUM_EXPORTS 25 typedef struct _ctypedescr CTypeDescrObject; @@ -156,41 +145,37 @@ assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \ (CTypeDescrObject *)_cffi_types[index]) -static int _cffi_init(void) +static PyObject *_cffi_init(char *module_name, Py_ssize_t version, + const struct _cffi_type_context_s *ctx) { - PyObject *module, *c_api_object = NULL; - void *src; + PyObject *module, *o_arg, *new_module; + void *raw[] = { + (void *)module_name, + (void *)version, + (void *)_cffi_exports, + (void *)ctx, + }; module = PyImport_ImportModule("_cffi_backend"); if (module == NULL) goto failure; - c_api_object = PyObject_GetAttrString(module, "_C_API"); - if (c_api_object == NULL) + o_arg = PyLong_FromVoidPtr((void *)raw); + if (o_arg == NULL) goto failure; - if (!PyCapsule_CheckExact(c_api_object)) { - PyErr_SetNone(PyExc_ImportError); - goto failure; - } - src = PyCapsule_GetPointer(c_api_object, "cffi"); - if ((uintptr_t)(((void **)src)[0]) < _CFFI_NUM_EXPORTS) { - PyErr_SetString(PyExc_ImportError, - "the _cffi_backend module is an outdated version"); - goto failure; - } - memcpy(_cffi_exports, src, _CFFI_NUM_EXPORTS * sizeof(void *)); + new_module = PyObject_CallMethod( + module, "_init_cffi_1_0_external_module", "O", o_arg); + + Py_DECREF(o_arg); Py_DECREF(module); - Py_DECREF(c_api_object); - return 0; + return new_module; failure: Py_XDECREF(module); - Py_XDECREF(c_api_object); - return -1; + return NULL; } - #endif /********** end CPython-specific section **********/ diff --git a/_cffi1/cffi1_module.c b/_cffi1/cffi1_module.c --- a/_cffi1/cffi1_module.c +++ b/_cffi1/cffi1_module.c @@ -103,16 +103,9 @@ return -1; } -static PyObject *_cffi_init_module(char *module_name, - const struct _cffi_type_context_s *ctx) +static PyObject *_my_Py_InitModule(char *module_name) { - PyObject *m; - FFIObject *ffi; - LibObject *lib; - #if PY_MAJOR_VERSION >= 3 - /* note: the module_def leaks, but anyway the C extension module cannot - be unloaded */ struct PyModuleDef *module_def, local_module_def = { PyModuleDef_HEAD_INIT, module_name, @@ -120,17 +113,57 @@ -1, NULL, NULL, NULL, NULL, NULL }; + /* note: the 'module_def' is allocated dynamically and leaks, + but anyway the C extension module can never be unloaded */ module_def = PyMem_Malloc(sizeof(struct PyModuleDef)); if (module_def == NULL) return PyErr_NoMemory(); *module_def = local_module_def; - m = PyModule_Create(module_def); + return PyModule_Create(module_def); #else - m = Py_InitModule(module_name, NULL); + return Py_InitModule(module_name, NULL); #endif +} + +#define CFFI_VERSION_MIN 0x2600 +#define CFFI_VERSION_MAX 0x260F + +static PyObject *b_init_cffi_1_0_external_module(PyObject *self, PyObject *arg) +{ + PyObject *m; + FFIObject *ffi; + LibObject *lib; + Py_ssize_t version; + char *module_name, *exports; + void **raw; + const struct _cffi_type_context_s *ctx; + + raw = (void **)PyLong_AsVoidPtr(arg); + if (raw == NULL) + return NULL; + + module_name = (char *)raw[0]; + version = (Py_ssize_t)raw[1]; + exports = (char *)raw[2]; + ctx = (const struct _cffi_type_context_s *)raw[3]; + + if (version < CFFI_VERSION_MIN || version > CFFI_VERSION_MAX) { + if (!PyErr_Occurred()) + PyErr_Format(PyExc_ImportError, + "cffi extension module '%s' has unknown version %p", + module_name, (void *)version); + return NULL; + } + + /* initialize the exports array */ + memcpy(exports, (char *)cffi_exports, sizeof(cffi_exports)); + + /* make the module object */ + m = _my_Py_InitModule(module_name); if (m == NULL) return NULL; + /* build the FFI and Lib object inside this new module */ ffi = ffi_internal_new(&FFI_Type, ctx); Py_XINCREF(ffi); /* make the ffi object really immortal */ if (ffi == NULL || PyModule_AddObject(m, "ffi", (PyObject *)ffi) < 0) diff --git a/_cffi1/recompiler.py b/_cffi1/recompiler.py --- a/_cffi1/recompiler.py +++ b/_cffi1/recompiler.py @@ -227,7 +227,7 @@ prnt('};') prnt() # - # the init function, loading _cffi_backend and calling a method there + # the init function base_module_name = self.module_name.split('.')[-1] prnt('#ifdef PYPY_VERSION') prnt('PyMODINIT_FUNC') @@ -251,18 +251,14 @@ prnt('PyMODINIT_FUNC') prnt('PyInit_%s(void)' % (base_module_name,)) prnt('{') - prnt(' if (_cffi_init() < 0)') - prnt(' return NULL;') - prnt(' return _cffi_init_module("%s", &_cffi_type_context);' % ( + prnt(' return _cffi_init("%s", 0x2600, &_cffi_type_context);' % ( self.module_name,)) prnt('}') prnt('#else') prnt('PyMODINIT_FUNC') prnt('init%s(void)' % (base_module_name,)) prnt('{') - prnt(' if (_cffi_init() < 0)') - prnt(' return;') - prnt(' _cffi_init_module("%s", &_cffi_type_context);' % ( + prnt(' _cffi_init("%s", 0x2600, &_cffi_type_context);' % ( self.module_name,)) prnt('}') prnt('#endif') diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c --- a/c/_cffi_backend.c +++ b/c/_cffi_backend.c @@ -5763,6 +5763,10 @@ return Py_None; } +static PyObject *b_init_cffi_1_0_external_module(PyObject *, PyObject *); +/* forward, see _cffi1/cffi1_module.c */ + + static PyMethodDef FFIBackendMethods[] = { {"load_library", b_load_library, METH_VARARGS}, {"new_primitive_type", b_new_primitive_type, METH_VARARGS}, @@ -5796,6 +5800,7 @@ {"_get_types", b__get_types, METH_NOARGS}, {"_testfunc", b__testfunc, METH_VARARGS}, {"_testbuff", b__testbuff, METH_VARARGS}, + {"_init_cffi_1_0_external_module", b_init_cffi_1_0_external_module, METH_O}, {NULL, NULL} /* Sentinel */ }; @@ -5908,10 +5913,8 @@ } #endif -#include "../_cffi1/cffi1_module.c" - static void *cffi_exports[] = { - (void *)26, + NULL, _cffi_to_c_i8, _cffi_to_c_u8, _cffi_to_c_i16, @@ -5941,11 +5944,14 @@ _cffi_to_c__Bool, _prepare_pointer_call_argument, convert_array_from_object, - _cffi_init_module, }; /************************************************************/ +#include "../_cffi1/cffi1_module.c" + +/************************************************************/ + #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef FFIBackendModuleDef = { PyModuleDef_HEAD_INIT, @@ -6016,11 +6022,12 @@ "__name__", v) < 0) INITERROR; + /* this is for backward compatibility only */ v = PyCapsule_New((void *)cffi_exports, "cffi", NULL); if (v == NULL || PyModule_AddObject(m, "_C_API", v) < 0) INITERROR; - v = PyText_FromString("1.0.0b2"); + v = PyText_FromString("1.0.0"); if (v == NULL || PyModule_AddObject(m, "__version__", v) < 0) INITERROR; diff --git a/cffi/__init__.py b/cffi/__init__.py --- a/cffi/__init__.py +++ b/cffi/__init__.py @@ -4,8 +4,8 @@ from .api import FFI, CDefError, FFIError from .ffiplatform import VerificationError, VerificationMissing -__version__ = "1.0.0b2" -__version_info__ = (1, 0, 0, "beta", 2) +__version__ = "1.0.0" +__version_info__ = (1, 0, 0) # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit