aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/cffi/c/lib_obj.c
diff options
context:
space:
mode:
authorolegts <olegts@yandex-team.ru>2022-02-10 16:48:22 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:48:22 +0300
commit30983fb2586f6904aaf6a5d6ef2b445cbaec1f44 (patch)
tree3e86334ffd140d7ccfa0aa79386a6cf51b5b1e46 /contrib/python/cffi/c/lib_obj.c
parent9525b12aeec0b37aae9be1712d3d1031a235118f (diff)
downloadydb-30983fb2586f6904aaf6a5d6ef2b445cbaec1f44.tar.gz
Restoring authorship annotation for <olegts@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/cffi/c/lib_obj.c')
-rw-r--r--contrib/python/cffi/c/lib_obj.c1340
1 files changed, 670 insertions, 670 deletions
diff --git a/contrib/python/cffi/c/lib_obj.c b/contrib/python/cffi/c/lib_obj.c
index 38bf3d5510..d253f5613a 100644
--- a/contrib/python/cffi/c/lib_obj.c
+++ b/contrib/python/cffi/c/lib_obj.c
@@ -1,166 +1,166 @@
-
-/* A Lib object is what is in the "lib" attribute of a C extension
- module originally created by recompile().
-
- A Lib object is special in the sense that it has a custom
- __getattr__ which returns C globals, functions and constants. The
- original idea was to raise AttributeError for anything else, even
- attrs like '__class__', but it breaks various things; now, standard
- attrs are returned, but in the unlikely case where a user cdef()s
- the same name, then the standard attr is hidden (and the various
- things like introspection might break).
-
- A Lib object has got a reference to the _cffi_type_context_s
- structure, which is used to create lazily the objects returned by
- __getattr__.
-*/
-
-struct CPyExtFunc_s {
- PyMethodDef md;
- void *direct_fn;
- int type_index;
- char doc[1];
-};
-
-struct LibObject_s {
- PyObject_HEAD
- builder_c_t *l_types_builder; /* same as the one on the ffi object */
- PyObject *l_dict; /* content, built lazily */
- PyObject *l_libname; /* some string that gives the name of the lib */
- FFIObject *l_ffi; /* reference back to the ffi object */
- void *l_libhandle; /* the dlopen()ed handle, if any */
+
+/* A Lib object is what is in the "lib" attribute of a C extension
+ module originally created by recompile().
+
+ A Lib object is special in the sense that it has a custom
+ __getattr__ which returns C globals, functions and constants. The
+ original idea was to raise AttributeError for anything else, even
+ attrs like '__class__', but it breaks various things; now, standard
+ attrs are returned, but in the unlikely case where a user cdef()s
+ the same name, then the standard attr is hidden (and the various
+ things like introspection might break).
+
+ A Lib object has got a reference to the _cffi_type_context_s
+ structure, which is used to create lazily the objects returned by
+ __getattr__.
+*/
+
+struct CPyExtFunc_s {
+ PyMethodDef md;
+ void *direct_fn;
+ int type_index;
+ char doc[1];
+};
+
+struct LibObject_s {
+ PyObject_HEAD
+ builder_c_t *l_types_builder; /* same as the one on the ffi object */
+ PyObject *l_dict; /* content, built lazily */
+ PyObject *l_libname; /* some string that gives the name of the lib */
+ FFIObject *l_ffi; /* reference back to the ffi object */
+ void *l_libhandle; /* the dlopen()ed handle, if any */
int l_auto_close; /* if we must dlclose() this handle */
-};
-
-static struct CPyExtFunc_s *_cpyextfunc_get(PyObject *x)
-{
- PyObject *y;
- LibObject *lo;
- PyCFunctionObject *fo;
-
- if (!PyCFunction_Check(x))
- return NULL;
- y = PyCFunction_GET_SELF(x);
- if (!LibObject_Check(y))
- return NULL;
-
- fo = (PyCFunctionObject *)x;
- lo = (LibObject *)y;
- if (lo->l_libname != fo->m_module)
- return NULL;
-
- return (struct CPyExtFunc_s *)(fo->m_ml);
-}
-
-static PyObject *_cpyextfunc_type(LibObject *lib, struct CPyExtFunc_s *exf)
-{
- PyObject *tuple, *result;
- tuple = realize_c_type_or_func(lib->l_types_builder,
- lib->l_types_builder->ctx.types,
- exf->type_index);
- if (tuple == NULL)
- return NULL;
-
- /* 'tuple' is a tuple of length 1 containing the real CT_FUNCTIONPTR
- object */
- result = PyTuple_GetItem(tuple, 0);
- Py_XINCREF(result);
- Py_DECREF(tuple);
- return result;
-}
-
-static PyObject *_cpyextfunc_type_index(PyObject *x)
-{
- struct CPyExtFunc_s *exf;
- LibObject *lib;
-
- assert(PyErr_Occurred());
- exf = _cpyextfunc_get(x);
- if (exf == NULL)
- return NULL; /* still the same exception is set */
-
- PyErr_Clear();
-
- lib = (LibObject *)PyCFunction_GET_SELF(x);
- return _cpyextfunc_type(lib, exf);
-}
-
-static void cdlopen_close_ignore_errors(void *libhandle); /* forward */
+};
+
+static struct CPyExtFunc_s *_cpyextfunc_get(PyObject *x)
+{
+ PyObject *y;
+ LibObject *lo;
+ PyCFunctionObject *fo;
+
+ if (!PyCFunction_Check(x))
+ return NULL;
+ y = PyCFunction_GET_SELF(x);
+ if (!LibObject_Check(y))
+ return NULL;
+
+ fo = (PyCFunctionObject *)x;
+ lo = (LibObject *)y;
+ if (lo->l_libname != fo->m_module)
+ return NULL;
+
+ return (struct CPyExtFunc_s *)(fo->m_ml);
+}
+
+static PyObject *_cpyextfunc_type(LibObject *lib, struct CPyExtFunc_s *exf)
+{
+ PyObject *tuple, *result;
+ tuple = realize_c_type_or_func(lib->l_types_builder,
+ lib->l_types_builder->ctx.types,
+ exf->type_index);
+ if (tuple == NULL)
+ return NULL;
+
+ /* 'tuple' is a tuple of length 1 containing the real CT_FUNCTIONPTR
+ object */
+ result = PyTuple_GetItem(tuple, 0);
+ Py_XINCREF(result);
+ Py_DECREF(tuple);
+ return result;
+}
+
+static PyObject *_cpyextfunc_type_index(PyObject *x)
+{
+ struct CPyExtFunc_s *exf;
+ LibObject *lib;
+
+ assert(PyErr_Occurred());
+ exf = _cpyextfunc_get(x);
+ if (exf == NULL)
+ return NULL; /* still the same exception is set */
+
+ PyErr_Clear();
+
+ lib = (LibObject *)PyCFunction_GET_SELF(x);
+ return _cpyextfunc_type(lib, exf);
+}
+
+static void cdlopen_close_ignore_errors(void *libhandle); /* forward */
static void *cdlopen_fetch(PyObject *libname, void *libhandle,
const char *symbol);
-
-static void lib_dealloc(LibObject *lib)
-{
+
+static void lib_dealloc(LibObject *lib)
+{
PyObject_GC_UnTrack(lib);
if (lib->l_auto_close)
cdlopen_close_ignore_errors(lib->l_libhandle);
- Py_DECREF(lib->l_dict);
- Py_DECREF(lib->l_libname);
- Py_DECREF(lib->l_ffi);
- PyObject_GC_Del(lib);
-}
-
-static int lib_traverse(LibObject *lib, visitproc visit, void *arg)
-{
- Py_VISIT(lib->l_dict);
- Py_VISIT(lib->l_libname);
- Py_VISIT(lib->l_ffi);
- return 0;
-}
-
-static PyObject *lib_repr(LibObject *lib)
-{
- return PyText_FromFormat("<Lib object for '%.200s'>",
- PyText_AS_UTF8(lib->l_libname));
-}
-
-static PyObject *lib_build_cpython_func(LibObject *lib,
- const struct _cffi_global_s *g,
- const char *s, int flags)
-{
- /* First make sure the argument types and return type are really
- built. The C extension code can then assume that they are,
- by calling _cffi_type().
- */
- PyObject *result = NULL;
- CTypeDescrObject **pfargs = NULL;
- CTypeDescrObject *fresult;
- Py_ssize_t nargs = 0;
- struct CPyExtFunc_s *xfunc;
- int i, type_index = _CFFI_GETARG(g->type_op);
- _cffi_opcode_t *opcodes = lib->l_types_builder->ctx.types;
- static const char *const format = ";\n\nCFFI C function from %s.lib";
+ Py_DECREF(lib->l_dict);
+ Py_DECREF(lib->l_libname);
+ Py_DECREF(lib->l_ffi);
+ PyObject_GC_Del(lib);
+}
+
+static int lib_traverse(LibObject *lib, visitproc visit, void *arg)
+{
+ Py_VISIT(lib->l_dict);
+ Py_VISIT(lib->l_libname);
+ Py_VISIT(lib->l_ffi);
+ return 0;
+}
+
+static PyObject *lib_repr(LibObject *lib)
+{
+ return PyText_FromFormat("<Lib object for '%.200s'>",
+ PyText_AS_UTF8(lib->l_libname));
+}
+
+static PyObject *lib_build_cpython_func(LibObject *lib,
+ const struct _cffi_global_s *g,
+ const char *s, int flags)
+{
+ /* First make sure the argument types and return type are really
+ built. The C extension code can then assume that they are,
+ by calling _cffi_type().
+ */
+ PyObject *result = NULL;
+ CTypeDescrObject **pfargs = NULL;
+ CTypeDescrObject *fresult;
+ Py_ssize_t nargs = 0;
+ struct CPyExtFunc_s *xfunc;
+ int i, type_index = _CFFI_GETARG(g->type_op);
+ _cffi_opcode_t *opcodes = lib->l_types_builder->ctx.types;
+ static const char *const format = ";\n\nCFFI C function from %s.lib";
const char *libname = PyText_AS_UTF8(lib->l_libname);
- struct funcbuilder_s funcbuilder;
-
- /* return type: */
- fresult = realize_c_func_return_type(lib->l_types_builder, opcodes,
- type_index);
- if (fresult == NULL)
- goto error;
-
- /* argument types: */
- /* note that if the arguments are already built, they have a
- pointer in the 'opcodes' array, and GETOP() returns a
- random even value. But OP_FUNCTION_END is odd, so the
- condition below still works correctly. */
- i = type_index + 1;
- while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END)
- i++;
- pfargs = alloca(sizeof(CTypeDescrObject *) * (i - type_index - 1));
- i = type_index + 1;
- while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END) {
- CTypeDescrObject *ct = realize_c_type(lib->l_types_builder, opcodes, i);
- if (ct == NULL)
- goto error;
- pfargs[nargs++] = ct;
- i++;
- }
-
- memset(&funcbuilder, 0, sizeof(funcbuilder));
- if (fb_build_name(&funcbuilder, g->name, pfargs, nargs, fresult, 0) < 0)
- goto error;
-
+ struct funcbuilder_s funcbuilder;
+
+ /* return type: */
+ fresult = realize_c_func_return_type(lib->l_types_builder, opcodes,
+ type_index);
+ if (fresult == NULL)
+ goto error;
+
+ /* argument types: */
+ /* note that if the arguments are already built, they have a
+ pointer in the 'opcodes' array, and GETOP() returns a
+ random even value. But OP_FUNCTION_END is odd, so the
+ condition below still works correctly. */
+ i = type_index + 1;
+ while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END)
+ i++;
+ pfargs = alloca(sizeof(CTypeDescrObject *) * (i - type_index - 1));
+ i = type_index + 1;
+ while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END) {
+ CTypeDescrObject *ct = realize_c_type(lib->l_types_builder, opcodes, i);
+ if (ct == NULL)
+ goto error;
+ pfargs[nargs++] = ct;
+ i++;
+ }
+
+ memset(&funcbuilder, 0, sizeof(funcbuilder));
+ if (fb_build_name(&funcbuilder, g->name, pfargs, nargs, fresult, 0) < 0)
+ goto error;
+
/* The few bytes of memory we allocate here appear to leak, but
this is not a real leak. Indeed, CPython never unloads its C
extension modules. There is only one PyMem_Malloc() per real
@@ -169,157 +169,157 @@ static PyObject *lib_build_cpython_func(LibObject *lib,
global variable generated for each CPYTHON_BLTN defined in the
C extension, and the effect would be the same (but a bit more
complicated).
- */
- xfunc = PyMem_Malloc(sizeof(struct CPyExtFunc_s) +
- funcbuilder.nb_bytes +
- strlen(format) + strlen(libname));
- if (xfunc == NULL) {
- PyErr_NoMemory();
- goto error;
- }
- memset((char *)xfunc, 0, sizeof(struct CPyExtFunc_s));
- assert(g->address);
- xfunc->md.ml_meth = (PyCFunction)g->address;
- xfunc->md.ml_flags = flags;
- xfunc->md.ml_name = g->name;
- xfunc->md.ml_doc = xfunc->doc;
- xfunc->direct_fn = g->size_or_direct_fn;
- xfunc->type_index = type_index;
-
- /* build the docstring */
- funcbuilder.bufferp = xfunc->doc;
- if (fb_build_name(&funcbuilder, g->name, pfargs, nargs, fresult, 0) < 0)
- goto error;
- sprintf(funcbuilder.bufferp - 1, format, libname);
- /* done building the docstring */
-
- result = PyCFunction_NewEx(&xfunc->md, (PyObject *)lib, lib->l_libname);
- /* fall-through */
- error:
- Py_XDECREF(fresult);
- while (nargs > 0) {
- --nargs;
- Py_DECREF(pfargs[nargs]);
- }
- return result;
-}
-
-static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name,
- int recursion)
-{
- /* does not return a new reference! */
- PyObject *x;
- int index;
- const struct _cffi_global_s *g;
- CTypeDescrObject *ct;
- builder_c_t *types_builder = lib->l_types_builder;
+ */
+ xfunc = PyMem_Malloc(sizeof(struct CPyExtFunc_s) +
+ funcbuilder.nb_bytes +
+ strlen(format) + strlen(libname));
+ if (xfunc == NULL) {
+ PyErr_NoMemory();
+ goto error;
+ }
+ memset((char *)xfunc, 0, sizeof(struct CPyExtFunc_s));
+ assert(g->address);
+ xfunc->md.ml_meth = (PyCFunction)g->address;
+ xfunc->md.ml_flags = flags;
+ xfunc->md.ml_name = g->name;
+ xfunc->md.ml_doc = xfunc->doc;
+ xfunc->direct_fn = g->size_or_direct_fn;
+ xfunc->type_index = type_index;
+
+ /* build the docstring */
+ funcbuilder.bufferp = xfunc->doc;
+ if (fb_build_name(&funcbuilder, g->name, pfargs, nargs, fresult, 0) < 0)
+ goto error;
+ sprintf(funcbuilder.bufferp - 1, format, libname);
+ /* done building the docstring */
+
+ result = PyCFunction_NewEx(&xfunc->md, (PyObject *)lib, lib->l_libname);
+ /* fall-through */
+ error:
+ Py_XDECREF(fresult);
+ while (nargs > 0) {
+ --nargs;
+ Py_DECREF(pfargs[nargs]);
+ }
+ return result;
+}
+
+static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name,
+ int recursion)
+{
+ /* does not return a new reference! */
+ PyObject *x;
+ int index;
+ const struct _cffi_global_s *g;
+ CTypeDescrObject *ct;
+ builder_c_t *types_builder = lib->l_types_builder;
const char *s = PyText_AsUTF8(name);
- if (s == NULL)
- return NULL;
-
- index = search_in_globals(&types_builder->ctx, s, strlen(s));
- if (index < 0) {
-
- if (types_builder->included_libs != NULL) {
- Py_ssize_t i;
- PyObject *included_ffis = types_builder->included_ffis;
- PyObject *included_libs = types_builder->included_libs;
-
- if (recursion > 100) {
- PyErr_SetString(PyExc_RuntimeError,
- "recursion overflow in ffi.include() delegations");
- return NULL;
- }
-
- for (i = 0; i < PyTuple_GET_SIZE(included_libs); i++) {
- LibObject *lib1;
-
- lib1 = (LibObject *)PyTuple_GET_ITEM(included_libs, i);
- if (lib1 != NULL) {
- x = PyDict_GetItem(lib1->l_dict, name);
- if (x != NULL) {
- Py_INCREF(x);
- goto found;
- }
- x = lib_build_and_cache_attr(lib1, name, recursion + 1);
- if (x != NULL) {
- Py_INCREF(x);
- goto found;
- }
- }
- else {
- FFIObject *ffi1;
-
- ffi1 = (FFIObject *)PyTuple_GetItem(included_ffis, i);
- if (ffi1 == NULL)
- return NULL;
- x = ffi_fetch_int_constant(ffi1, s, recursion + 1);
- if (x != NULL)
- goto found;
- }
- if (PyErr_Occurred())
- return NULL;
- }
- }
-
- if (recursion > 0)
- return NULL; /* no error set, continue looking elsewhere */
-
- PyErr_Format(PyExc_AttributeError,
- "cffi library '%.200s' has no function, constant "
- "or global variable named '%.200s'",
- PyText_AS_UTF8(lib->l_libname), s);
- return NULL;
- }
-
- g = &types_builder->ctx.globals[index];
-
- switch (_CFFI_GETOP(g->type_op)) {
-
- case _CFFI_OP_CPYTHON_BLTN_V:
- x = lib_build_cpython_func(lib, g, s, METH_VARARGS);
- break;
-
- case _CFFI_OP_CPYTHON_BLTN_N:
- x = lib_build_cpython_func(lib, g, s, METH_NOARGS);
- break;
-
- case _CFFI_OP_CPYTHON_BLTN_O:
- x = lib_build_cpython_func(lib, g, s, METH_O);
- break;
-
- case _CFFI_OP_CONSTANT_INT:
- case _CFFI_OP_ENUM:
- {
- /* a constant integer whose value, in an "unsigned long long",
- is obtained by calling the function at g->address */
- x = realize_global_int(types_builder, index);
- break;
- }
-
- case _CFFI_OP_CONSTANT:
- case _CFFI_OP_DLOPEN_CONST:
- {
- /* a constant which is not of integer type */
- char *data;
- ct = realize_c_type(types_builder, types_builder->ctx.types,
- _CFFI_GETARG(g->type_op));
- if (ct == NULL)
- return NULL;
-
- if (ct->ct_size <= 0) {
- PyErr_Format(FFIError, "constant '%s' is of type '%s', "
- "whose size is not known", s, ct->ct_name);
- return NULL;
- }
- if (g->address == NULL) {
- /* for dlopen() style */
- assert(_CFFI_GETOP(g->type_op) == _CFFI_OP_DLOPEN_CONST);
- data = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
- if (data == NULL)
- return NULL;
- }
- else {
+ if (s == NULL)
+ return NULL;
+
+ index = search_in_globals(&types_builder->ctx, s, strlen(s));
+ if (index < 0) {
+
+ if (types_builder->included_libs != NULL) {
+ Py_ssize_t i;
+ PyObject *included_ffis = types_builder->included_ffis;
+ PyObject *included_libs = types_builder->included_libs;
+
+ if (recursion > 100) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "recursion overflow in ffi.include() delegations");
+ return NULL;
+ }
+
+ for (i = 0; i < PyTuple_GET_SIZE(included_libs); i++) {
+ LibObject *lib1;
+
+ lib1 = (LibObject *)PyTuple_GET_ITEM(included_libs, i);
+ if (lib1 != NULL) {
+ x = PyDict_GetItem(lib1->l_dict, name);
+ if (x != NULL) {
+ Py_INCREF(x);
+ goto found;
+ }
+ x = lib_build_and_cache_attr(lib1, name, recursion + 1);
+ if (x != NULL) {
+ Py_INCREF(x);
+ goto found;
+ }
+ }
+ else {
+ FFIObject *ffi1;
+
+ ffi1 = (FFIObject *)PyTuple_GetItem(included_ffis, i);
+ if (ffi1 == NULL)
+ return NULL;
+ x = ffi_fetch_int_constant(ffi1, s, recursion + 1);
+ if (x != NULL)
+ goto found;
+ }
+ if (PyErr_Occurred())
+ return NULL;
+ }
+ }
+
+ if (recursion > 0)
+ return NULL; /* no error set, continue looking elsewhere */
+
+ PyErr_Format(PyExc_AttributeError,
+ "cffi library '%.200s' has no function, constant "
+ "or global variable named '%.200s'",
+ PyText_AS_UTF8(lib->l_libname), s);
+ return NULL;
+ }
+
+ g = &types_builder->ctx.globals[index];
+
+ switch (_CFFI_GETOP(g->type_op)) {
+
+ case _CFFI_OP_CPYTHON_BLTN_V:
+ x = lib_build_cpython_func(lib, g, s, METH_VARARGS);
+ break;
+
+ case _CFFI_OP_CPYTHON_BLTN_N:
+ x = lib_build_cpython_func(lib, g, s, METH_NOARGS);
+ break;
+
+ case _CFFI_OP_CPYTHON_BLTN_O:
+ x = lib_build_cpython_func(lib, g, s, METH_O);
+ break;
+
+ case _CFFI_OP_CONSTANT_INT:
+ case _CFFI_OP_ENUM:
+ {
+ /* a constant integer whose value, in an "unsigned long long",
+ is obtained by calling the function at g->address */
+ x = realize_global_int(types_builder, index);
+ break;
+ }
+
+ case _CFFI_OP_CONSTANT:
+ case _CFFI_OP_DLOPEN_CONST:
+ {
+ /* a constant which is not of integer type */
+ char *data;
+ ct = realize_c_type(types_builder, types_builder->ctx.types,
+ _CFFI_GETARG(g->type_op));
+ if (ct == NULL)
+ return NULL;
+
+ if (ct->ct_size <= 0) {
+ PyErr_Format(FFIError, "constant '%s' is of type '%s', "
+ "whose size is not known", s, ct->ct_name);
+ return NULL;
+ }
+ if (g->address == NULL) {
+ /* for dlopen() style */
+ assert(_CFFI_GETOP(g->type_op) == _CFFI_OP_DLOPEN_CONST);
+ data = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
+ if (data == NULL)
+ return NULL;
+ }
+ else {
/* The few bytes of memory we allocate here appear to leak, but
this is not a real leak. Indeed, CPython never unloads its C
extension modules. There is only one PyMem_Malloc() per real
@@ -334,218 +334,218 @@ static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name,
cases; but there is no point and it only makes the remaining
less-common cases more suspicious.
*/
- assert(_CFFI_GETOP(g->type_op) == _CFFI_OP_CONSTANT);
- data = PyMem_Malloc(ct->ct_size);
- if (data == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- ((void(*)(char*))g->address)(data);
- }
- x = convert_to_object(data, ct);
- Py_DECREF(ct);
- break;
- }
-
- case _CFFI_OP_GLOBAL_VAR:
- {
- /* global variable of the exact type specified here
- (nowadays, only used by the ABI mode or backward
- compatibility; see _CFFI_OP_GLOBAL_VAR_F for the API mode)
- */
- Py_ssize_t g_size = (Py_ssize_t)g->size_or_direct_fn;
- ct = realize_c_type(types_builder, types_builder->ctx.types,
- _CFFI_GETARG(g->type_op));
- if (ct == NULL)
- return NULL;
- if (g_size != ct->ct_size && g_size != 0 && ct->ct_size > 0) {
- PyErr_Format(FFIError,
- "global variable '%.200s' should be %zd bytes "
- "according to the cdef, but is actually %zd",
- s, ct->ct_size, g_size);
- x = NULL;
- }
- else {
- void *address = g->address;
- if (address == NULL) {
- /* for dlopen() style */
- address = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
- if (address == NULL)
- return NULL;
- }
- x = make_global_var(name, ct, address, NULL);
- }
- Py_DECREF(ct);
- break;
- }
-
- case _CFFI_OP_GLOBAL_VAR_F:
- ct = realize_c_type(types_builder, types_builder->ctx.types,
- _CFFI_GETARG(g->type_op));
- if (ct == NULL)
- return NULL;
- x = make_global_var(name, ct, NULL, (gs_fetch_addr_fn)g->address);
- Py_DECREF(ct);
- break;
-
- case _CFFI_OP_DLOPEN_FUNC:
- {
- /* For dlopen(): the function of the given 'name'. We use
- dlsym() to get the address of something in the dynamic
- library, which we interpret as being exactly a function of
- the specified type.
- */
- PyObject *ct1;
- void *address = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
- if (address == NULL)
- return NULL;
-
- ct1 = realize_c_type_or_func(types_builder,
- types_builder->ctx.types,
- _CFFI_GETARG(g->type_op));
- if (ct1 == NULL)
- return NULL;
-
- assert(!CTypeDescr_Check(ct1)); /* must be a function */
- x = new_simple_cdata(address, unwrap_fn_as_fnptr(ct1));
-
- Py_DECREF(ct1);
- break;
- }
-
- case _CFFI_OP_EXTERN_PYTHON:
- /* for reading 'lib.bar' where bar is declared with extern "Python" */
- ct = realize_c_type(types_builder, types_builder->ctx.types,
- _CFFI_GETARG(g->type_op));
- if (ct == NULL)
- return NULL;
- x = convert_to_object((char *)&g->size_or_direct_fn, ct);
- Py_DECREF(ct);
- break;
-
- default:
- PyErr_Format(PyExc_NotImplementedError, "in lib_build_attr: op=%d",
- (int)_CFFI_GETOP(g->type_op));
- return NULL;
- }
-
- found:
- if (x != NULL) {
- int err = PyDict_SetItem(lib->l_dict, name, x);
- Py_DECREF(x);
- if (err < 0) /* else there is still one ref left in the dict */
- return NULL;
- }
- return x;
-}
-
-#define LIB_GET_OR_CACHE_ADDR(x, lib, name, error) \
- do { \
- x = PyDict_GetItem(lib->l_dict, name); \
- if (x == NULL) { \
- x = lib_build_and_cache_attr(lib, name, 0); \
- if (x == NULL) { \
- error; \
- } \
- } \
- } while (0)
-
-static PyObject *_lib_dir1(LibObject *lib, int ignore_global_vars)
-{
- const struct _cffi_global_s *g = lib->l_types_builder->ctx.globals;
- int i, count = 0, total = lib->l_types_builder->ctx.num_globals;
- PyObject *s, *lst = PyList_New(total);
- if (lst == NULL)
- return NULL;
-
- for (i = 0; i < total; i++) {
- if (ignore_global_vars) {
- int op = _CFFI_GETOP(g[i].type_op);
- if (op == _CFFI_OP_GLOBAL_VAR || op == _CFFI_OP_GLOBAL_VAR_F)
- continue;
- }
- s = PyText_FromString(g[i].name);
- if (s == NULL)
- goto error;
- PyList_SET_ITEM(lst, count, s);
- count++;
- }
- if (PyList_SetSlice(lst, count, total, NULL) < 0)
- goto error;
- return lst;
-
- error:
- Py_DECREF(lst);
- return NULL;
-}
-
-static PyObject *_lib_dict(LibObject *lib)
-{
- const struct _cffi_global_s *g = lib->l_types_builder->ctx.globals;
- int i, total = lib->l_types_builder->ctx.num_globals;
- PyObject *name, *x, *d = PyDict_New();
- if (d == NULL)
- return NULL;
-
- for (i = 0; i < total; i++) {
- name = PyText_FromString(g[i].name);
- if (name == NULL)
- goto error;
-
- LIB_GET_OR_CACHE_ADDR(x, lib, name, goto error);
-
- if (PyDict_SetItem(d, name, x) < 0)
- goto error;
- Py_DECREF(name);
- }
- return d;
-
- error:
- Py_XDECREF(name);
- Py_DECREF(d);
- return NULL;
-}
-
-static PyObject *lib_getattr(LibObject *lib, PyObject *name)
-{
+ assert(_CFFI_GETOP(g->type_op) == _CFFI_OP_CONSTANT);
+ data = PyMem_Malloc(ct->ct_size);
+ if (data == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ ((void(*)(char*))g->address)(data);
+ }
+ x = convert_to_object(data, ct);
+ Py_DECREF(ct);
+ break;
+ }
+
+ case _CFFI_OP_GLOBAL_VAR:
+ {
+ /* global variable of the exact type specified here
+ (nowadays, only used by the ABI mode or backward
+ compatibility; see _CFFI_OP_GLOBAL_VAR_F for the API mode)
+ */
+ Py_ssize_t g_size = (Py_ssize_t)g->size_or_direct_fn;
+ ct = realize_c_type(types_builder, types_builder->ctx.types,
+ _CFFI_GETARG(g->type_op));
+ if (ct == NULL)
+ return NULL;
+ if (g_size != ct->ct_size && g_size != 0 && ct->ct_size > 0) {
+ PyErr_Format(FFIError,
+ "global variable '%.200s' should be %zd bytes "
+ "according to the cdef, but is actually %zd",
+ s, ct->ct_size, g_size);
+ x = NULL;
+ }
+ else {
+ void *address = g->address;
+ if (address == NULL) {
+ /* for dlopen() style */
+ address = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
+ if (address == NULL)
+ return NULL;
+ }
+ x = make_global_var(name, ct, address, NULL);
+ }
+ Py_DECREF(ct);
+ break;
+ }
+
+ case _CFFI_OP_GLOBAL_VAR_F:
+ ct = realize_c_type(types_builder, types_builder->ctx.types,
+ _CFFI_GETARG(g->type_op));
+ if (ct == NULL)
+ return NULL;
+ x = make_global_var(name, ct, NULL, (gs_fetch_addr_fn)g->address);
+ Py_DECREF(ct);
+ break;
+
+ case _CFFI_OP_DLOPEN_FUNC:
+ {
+ /* For dlopen(): the function of the given 'name'. We use
+ dlsym() to get the address of something in the dynamic
+ library, which we interpret as being exactly a function of
+ the specified type.
+ */
+ PyObject *ct1;
+ void *address = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
+ if (address == NULL)
+ return NULL;
+
+ ct1 = realize_c_type_or_func(types_builder,
+ types_builder->ctx.types,
+ _CFFI_GETARG(g->type_op));
+ if (ct1 == NULL)
+ return NULL;
+
+ assert(!CTypeDescr_Check(ct1)); /* must be a function */
+ x = new_simple_cdata(address, unwrap_fn_as_fnptr(ct1));
+
+ Py_DECREF(ct1);
+ break;
+ }
+
+ case _CFFI_OP_EXTERN_PYTHON:
+ /* for reading 'lib.bar' where bar is declared with extern "Python" */
+ ct = realize_c_type(types_builder, types_builder->ctx.types,
+ _CFFI_GETARG(g->type_op));
+ if (ct == NULL)
+ return NULL;
+ x = convert_to_object((char *)&g->size_or_direct_fn, ct);
+ Py_DECREF(ct);
+ break;
+
+ default:
+ PyErr_Format(PyExc_NotImplementedError, "in lib_build_attr: op=%d",
+ (int)_CFFI_GETOP(g->type_op));
+ return NULL;
+ }
+
+ found:
+ if (x != NULL) {
+ int err = PyDict_SetItem(lib->l_dict, name, x);
+ Py_DECREF(x);
+ if (err < 0) /* else there is still one ref left in the dict */
+ return NULL;
+ }
+ return x;
+}
+
+#define LIB_GET_OR_CACHE_ADDR(x, lib, name, error) \
+ do { \
+ x = PyDict_GetItem(lib->l_dict, name); \
+ if (x == NULL) { \
+ x = lib_build_and_cache_attr(lib, name, 0); \
+ if (x == NULL) { \
+ error; \
+ } \
+ } \
+ } while (0)
+
+static PyObject *_lib_dir1(LibObject *lib, int ignore_global_vars)
+{
+ const struct _cffi_global_s *g = lib->l_types_builder->ctx.globals;
+ int i, count = 0, total = lib->l_types_builder->ctx.num_globals;
+ PyObject *s, *lst = PyList_New(total);
+ if (lst == NULL)
+ return NULL;
+
+ for (i = 0; i < total; i++) {
+ if (ignore_global_vars) {
+ int op = _CFFI_GETOP(g[i].type_op);
+ if (op == _CFFI_OP_GLOBAL_VAR || op == _CFFI_OP_GLOBAL_VAR_F)
+ continue;
+ }
+ s = PyText_FromString(g[i].name);
+ if (s == NULL)
+ goto error;
+ PyList_SET_ITEM(lst, count, s);
+ count++;
+ }
+ if (PyList_SetSlice(lst, count, total, NULL) < 0)
+ goto error;
+ return lst;
+
+ error:
+ Py_DECREF(lst);
+ return NULL;
+}
+
+static PyObject *_lib_dict(LibObject *lib)
+{
+ const struct _cffi_global_s *g = lib->l_types_builder->ctx.globals;
+ int i, total = lib->l_types_builder->ctx.num_globals;
+ PyObject *name, *x, *d = PyDict_New();
+ if (d == NULL)
+ return NULL;
+
+ for (i = 0; i < total; i++) {
+ name = PyText_FromString(g[i].name);
+ if (name == NULL)
+ goto error;
+
+ LIB_GET_OR_CACHE_ADDR(x, lib, name, goto error);
+
+ if (PyDict_SetItem(d, name, x) < 0)
+ goto error;
+ Py_DECREF(name);
+ }
+ return d;
+
+ error:
+ Py_XDECREF(name);
+ Py_DECREF(d);
+ return NULL;
+}
+
+static PyObject *lib_getattr(LibObject *lib, PyObject *name)
+{
const char *p;
- PyObject *x;
- LIB_GET_OR_CACHE_ADDR(x, lib, name, goto missing);
-
- if (GlobSupport_Check(x)) {
- return read_global_var((GlobSupportObject *)x);
- }
- Py_INCREF(x);
- return x;
-
- missing:
+ PyObject *x;
+ LIB_GET_OR_CACHE_ADDR(x, lib, name, goto missing);
+
+ if (GlobSupport_Check(x)) {
+ return read_global_var((GlobSupportObject *)x);
+ }
+ Py_INCREF(x);
+ return x;
+
+ missing:
/*** ATTRIBUTEERROR IS SET HERE ***/
- p = PyText_AsUTF8(name);
- if (p == NULL)
- return NULL;
- if (strcmp(p, "__all__") == 0) {
- PyErr_Clear();
- return _lib_dir1(lib, 1);
- }
- if (strcmp(p, "__dict__") == 0) {
- PyErr_Clear();
- return _lib_dict(lib);
- }
- if (strcmp(p, "__class__") == 0) {
- PyErr_Clear();
- x = (PyObject *)&PyModule_Type;
- /* ^^^ used to be Py_TYPE(lib). But HAAAAAACK! That makes
- help() behave correctly. I couldn't find a more reasonable
- way. Urgh. */
- Py_INCREF(x);
- return x;
- }
- /* this hack is for Python 3.5, and also to give a more
- module-like behavior */
- if (strcmp(p, "__name__") == 0) {
- PyErr_Clear();
- return PyText_FromFormat("%s.lib", PyText_AS_UTF8(lib->l_libname));
- }
+ p = PyText_AsUTF8(name);
+ if (p == NULL)
+ return NULL;
+ if (strcmp(p, "__all__") == 0) {
+ PyErr_Clear();
+ return _lib_dir1(lib, 1);
+ }
+ if (strcmp(p, "__dict__") == 0) {
+ PyErr_Clear();
+ return _lib_dict(lib);
+ }
+ if (strcmp(p, "__class__") == 0) {
+ PyErr_Clear();
+ x = (PyObject *)&PyModule_Type;
+ /* ^^^ used to be Py_TYPE(lib). But HAAAAAACK! That makes
+ help() behave correctly. I couldn't find a more reasonable
+ way. Urgh. */
+ Py_INCREF(x);
+ return x;
+ }
+ /* this hack is for Python 3.5, and also to give a more
+ module-like behavior */
+ if (strcmp(p, "__name__") == 0) {
+ PyErr_Clear();
+ return PyText_FromFormat("%s.lib", PyText_AS_UTF8(lib->l_libname));
+ }
#if PY_MAJOR_VERSION >= 3
if (strcmp(p, "__loader__") == 0 || strcmp(p, "__spec__") == 0) {
/* some more module-like behavior hacks */
@@ -554,163 +554,163 @@ static PyObject *lib_getattr(LibObject *lib, PyObject *name)
return Py_None;
}
#endif
- return NULL;
-}
-
-static int lib_setattr(LibObject *lib, PyObject *name, PyObject *val)
-{
- PyObject *x;
- LIB_GET_OR_CACHE_ADDR(x, lib, name, return -1);
-
- if (val == NULL) {
- PyErr_SetString(PyExc_AttributeError, "C attribute cannot be deleted");
- return -1;
- }
-
- if (GlobSupport_Check(x)) {
- return write_global_var((GlobSupportObject *)x, val);
- }
-
- PyErr_Format(PyExc_AttributeError,
- "cannot write to function or constant '%.200s'",
- PyText_Check(name) ? PyText_AS_UTF8(name) : "?");
- return -1;
-}
-
-static PyObject *lib_dir(PyObject *self, PyObject *noarg)
-{
- return _lib_dir1((LibObject *)self, 0);
-}
-
-static PyMethodDef lib_methods[] = {
- {"__dir__", lib_dir, METH_NOARGS},
- {NULL, NULL} /* sentinel */
-};
-
-static PyTypeObject Lib_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
+ return NULL;
+}
+
+static int lib_setattr(LibObject *lib, PyObject *name, PyObject *val)
+{
+ PyObject *x;
+ LIB_GET_OR_CACHE_ADDR(x, lib, name, return -1);
+
+ if (val == NULL) {
+ PyErr_SetString(PyExc_AttributeError, "C attribute cannot be deleted");
+ return -1;
+ }
+
+ if (GlobSupport_Check(x)) {
+ return write_global_var((GlobSupportObject *)x, val);
+ }
+
+ PyErr_Format(PyExc_AttributeError,
+ "cannot write to function or constant '%.200s'",
+ PyText_Check(name) ? PyText_AS_UTF8(name) : "?");
+ return -1;
+}
+
+static PyObject *lib_dir(PyObject *self, PyObject *noarg)
+{
+ return _lib_dir1((LibObject *)self, 0);
+}
+
+static PyMethodDef lib_methods[] = {
+ {"__dir__", lib_dir, METH_NOARGS},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyTypeObject Lib_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
"_cffi_backend.Lib",
- sizeof(LibObject),
- 0,
- (destructor)lib_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)lib_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- (getattrofunc)lib_getattr, /* tp_getattro */
- (setattrofunc)lib_setattr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- (traverseproc)lib_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- lib_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(LibObject, l_dict), /* tp_dictoffset */
-};
-
+ sizeof(LibObject),
+ 0,
+ (destructor)lib_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)lib_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ (getattrofunc)lib_getattr, /* tp_getattro */
+ (setattrofunc)lib_setattr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+ 0, /* tp_doc */
+ (traverseproc)lib_traverse, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ lib_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ offsetof(LibObject, l_dict), /* tp_dictoffset */
+};
+
static LibObject *lib_internal_new(FFIObject *ffi, const char *module_name,
void *dlopen_libhandle, int auto_close)
-{
- LibObject *lib;
- PyObject *libname, *dict;
-
- libname = PyText_FromString(module_name);
- if (libname == NULL)
- goto err1;
-
- dict = PyDict_New();
- if (dict == NULL)
- goto err2;
-
- lib = (LibObject *)PyType_GenericAlloc(&Lib_Type, 0);
- if (lib == NULL)
- goto err3;
-
- lib->l_types_builder = &ffi->types_builder;
- lib->l_dict = dict;
- lib->l_libname = libname;
- Py_INCREF(ffi);
- lib->l_ffi = ffi;
- lib->l_libhandle = dlopen_libhandle;
+{
+ LibObject *lib;
+ PyObject *libname, *dict;
+
+ libname = PyText_FromString(module_name);
+ if (libname == NULL)
+ goto err1;
+
+ dict = PyDict_New();
+ if (dict == NULL)
+ goto err2;
+
+ lib = (LibObject *)PyType_GenericAlloc(&Lib_Type, 0);
+ if (lib == NULL)
+ goto err3;
+
+ lib->l_types_builder = &ffi->types_builder;
+ lib->l_dict = dict;
+ lib->l_libname = libname;
+ Py_INCREF(ffi);
+ lib->l_ffi = ffi;
+ lib->l_libhandle = dlopen_libhandle;
lib->l_auto_close = auto_close;
- return lib;
-
- err3:
- Py_DECREF(dict);
- err2:
- Py_DECREF(libname);
- err1:
+ return lib;
+
+ err3:
+ Py_DECREF(dict);
+ err2:
+ Py_DECREF(libname);
+ err1:
if (auto_close)
cdlopen_close_ignore_errors(dlopen_libhandle);
- return NULL;
-}
-
-static PyObject *address_of_global_var(PyObject *args)
-{
- LibObject *lib;
- PyObject *x, *o_varname;
- char *varname;
-
- if (!PyArg_ParseTuple(args, "O!s", &Lib_Type, &lib, &varname))
- return NULL;
-
- /* rebuild a string from 'varname', to do typechecks and to force
- a unicode back to a plain string (on python 2) */
- o_varname = PyText_FromString(varname);
- if (o_varname == NULL)
- return NULL;
-
- LIB_GET_OR_CACHE_ADDR(x, lib, o_varname, goto error);
- Py_DECREF(o_varname);
- if (GlobSupport_Check(x)) {
- return cg_addressof_global_var((GlobSupportObject *)x);
- }
- else {
- struct CPyExtFunc_s *exf = _cpyextfunc_get(x);
- if (exf != NULL) { /* an OP_CPYTHON_BLTN: '&func' returns a cdata */
- PyObject *ct;
- if (exf->direct_fn == NULL) {
- Py_INCREF(x); /* backward compatibility */
- return x;
- }
- ct = _cpyextfunc_type(lib, exf);
- if (ct == NULL)
- return NULL;
- x = new_simple_cdata(exf->direct_fn, (CTypeDescrObject *)ct);
- Py_DECREF(ct);
- return x;
- }
- if (CData_Check(x) && /* a constant functionptr cdata: 'f == &f' */
- (((CDataObject *)x)->c_type->ct_flags & CT_FUNCTIONPTR) != 0) {
- Py_INCREF(x);
- return x;
- }
- else {
- PyErr_Format(PyExc_AttributeError,
- "cannot take the address of the constant '%.200s'",
- varname);
- return NULL;
- }
- }
-
- error:
- Py_DECREF(o_varname);
- return NULL;
-}
+ return NULL;
+}
+
+static PyObject *address_of_global_var(PyObject *args)
+{
+ LibObject *lib;
+ PyObject *x, *o_varname;
+ char *varname;
+
+ if (!PyArg_ParseTuple(args, "O!s", &Lib_Type, &lib, &varname))
+ return NULL;
+
+ /* rebuild a string from 'varname', to do typechecks and to force
+ a unicode back to a plain string (on python 2) */
+ o_varname = PyText_FromString(varname);
+ if (o_varname == NULL)
+ return NULL;
+
+ LIB_GET_OR_CACHE_ADDR(x, lib, o_varname, goto error);
+ Py_DECREF(o_varname);
+ if (GlobSupport_Check(x)) {
+ return cg_addressof_global_var((GlobSupportObject *)x);
+ }
+ else {
+ struct CPyExtFunc_s *exf = _cpyextfunc_get(x);
+ if (exf != NULL) { /* an OP_CPYTHON_BLTN: '&func' returns a cdata */
+ PyObject *ct;
+ if (exf->direct_fn == NULL) {
+ Py_INCREF(x); /* backward compatibility */
+ return x;
+ }
+ ct = _cpyextfunc_type(lib, exf);
+ if (ct == NULL)
+ return NULL;
+ x = new_simple_cdata(exf->direct_fn, (CTypeDescrObject *)ct);
+ Py_DECREF(ct);
+ return x;
+ }
+ if (CData_Check(x) && /* a constant functionptr cdata: 'f == &f' */
+ (((CDataObject *)x)->c_type->ct_flags & CT_FUNCTIONPTR) != 0) {
+ Py_INCREF(x);
+ return x;
+ }
+ else {
+ PyErr_Format(PyExc_AttributeError,
+ "cannot take the address of the constant '%.200s'",
+ varname);
+ return NULL;
+ }
+ }
+
+ error:
+ Py_DECREF(o_varname);
+ return NULL;
+}