mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
Implement PEP 3121: new module initialization and finalization API.
This commit is contained in:
parent
cdf94635d7
commit
1a21451b1d
113 changed files with 2230 additions and 855 deletions
|
@ -11,98 +11,6 @@ static PyObject *va_build_value(const char *, va_list, int);
|
|||
/* Package context -- the full module name for package imports */
|
||||
char *_Py_PackageContext = NULL;
|
||||
|
||||
/* Py_InitModule4() parameters:
|
||||
- name is the module name
|
||||
- methods is the list of top-level functions
|
||||
- doc is the documentation string
|
||||
- passthrough is passed as self to functions defined in the module
|
||||
- api_version is the value of PYTHON_API_VERSION at the time the
|
||||
module was compiled
|
||||
|
||||
Return value is a borrowed reference to the module object; or NULL
|
||||
if an error occurred (in Python 1.4 and before, errors were fatal).
|
||||
Errors may still leak memory.
|
||||
*/
|
||||
|
||||
static char api_version_warning[] =
|
||||
"Python C API version mismatch for module %.100s:\
|
||||
This Python has API version %d, module %.100s has version %d.";
|
||||
|
||||
PyObject *
|
||||
Py_InitModule4(const char *name, PyMethodDef *methods, const char *doc,
|
||||
PyObject *passthrough, int module_api_version)
|
||||
{
|
||||
PyObject *m, *d, *v, *n;
|
||||
PyMethodDef *ml;
|
||||
if (!Py_IsInitialized())
|
||||
Py_FatalError("Interpreter not initialized (version mismatch?)");
|
||||
if (module_api_version != PYTHON_API_VERSION) {
|
||||
char message[512];
|
||||
PyOS_snprintf(message, sizeof(message),
|
||||
api_version_warning, name,
|
||||
PYTHON_API_VERSION, name,
|
||||
module_api_version);
|
||||
if (PyErr_WarnEx(PyExc_RuntimeWarning, message, 1))
|
||||
return NULL;
|
||||
}
|
||||
/* Make sure name is fully qualified.
|
||||
|
||||
This is a bit of a hack: when the shared library is loaded,
|
||||
the module name is "package.module", but the module calls
|
||||
Py_InitModule*() with just "module" for the name. The shared
|
||||
library loader squirrels away the true name of the module in
|
||||
_Py_PackageContext, and Py_InitModule*() will substitute this
|
||||
(if the name actually matches).
|
||||
*/
|
||||
if (_Py_PackageContext != NULL) {
|
||||
char *p = strrchr(_Py_PackageContext, '.');
|
||||
if (p != NULL && strcmp(name, p+1) == 0) {
|
||||
name = _Py_PackageContext;
|
||||
_Py_PackageContext = NULL;
|
||||
}
|
||||
}
|
||||
if ((m = PyImport_AddModule(name)) == NULL)
|
||||
return NULL;
|
||||
d = PyModule_GetDict(m);
|
||||
if (methods != NULL) {
|
||||
n = PyUnicode_FromString(name);
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
for (ml = methods; ml->ml_name != NULL; ml++) {
|
||||
if ((ml->ml_flags & METH_CLASS) ||
|
||||
(ml->ml_flags & METH_STATIC)) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"module functions cannot set"
|
||||
" METH_CLASS or METH_STATIC");
|
||||
Py_DECREF(n);
|
||||
return NULL;
|
||||
}
|
||||
v = PyCFunction_NewEx(ml, passthrough, n);
|
||||
if (v == NULL) {
|
||||
Py_DECREF(n);
|
||||
return NULL;
|
||||
}
|
||||
if (PyDict_SetItemString(d, ml->ml_name, v) != 0) {
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(n);
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(v);
|
||||
}
|
||||
Py_DECREF(n);
|
||||
}
|
||||
if (doc != NULL) {
|
||||
v = PyUnicode_FromString(doc);
|
||||
if (v == NULL || PyDict_SetItemString(d, "__doc__", v) != 0) {
|
||||
Py_XDECREF(v);
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(v);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/* Helper for mkvalue() to scan the length of a format */
|
||||
|
||||
static int
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue