• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* A Lib object is what is in the "lib" attribute of a C extension
3    module originally created by recompile().
4 
5    A Lib object is special in the sense that it has a custom
6    __getattr__ which returns C globals, functions and constants.  The
7    original idea was to raise AttributeError for anything else, even
8    attrs like '__class__', but it breaks various things; now, standard
9    attrs are returned, but in the unlikely case where a user cdef()s
10    the same name, then the standard attr is hidden (and the various
11    things like introspection might break).
12 
13    A Lib object has got a reference to the _cffi_type_context_s
14    structure, which is used to create lazily the objects returned by
15    __getattr__.
16 */
17 
18 struct CPyExtFunc_s {
19     PyMethodDef md;
20     void *direct_fn;
21     int type_index;
22     char doc[1];
23 };
24 
25 struct LibObject_s {
26     PyObject_HEAD
27     builder_c_t *l_types_builder; /* same as the one on the ffi object */
28     PyObject *l_dict;           /* content, built lazily */
29     PyObject *l_libname;        /* some string that gives the name of the lib */
30     FFIObject *l_ffi;           /* reference back to the ffi object */
31     void *l_libhandle;          /* the dlopen()ed handle, if any */
32     int l_auto_close;           /* if we must dlclose() this handle */
33 };
34 
_cpyextfunc_get(PyObject * x)35 static struct CPyExtFunc_s *_cpyextfunc_get(PyObject *x)
36 {
37     PyObject *y;
38     LibObject *lo;
39     PyCFunctionObject *fo;
40 
41     if (!PyCFunction_Check(x))
42         return NULL;
43     y = PyCFunction_GET_SELF(x);
44     if (!LibObject_Check(y))
45         return NULL;
46 
47     fo = (PyCFunctionObject *)x;
48     lo = (LibObject *)y;
49     if (lo->l_libname != fo->m_module)
50         return NULL;
51 
52     return (struct CPyExtFunc_s *)(fo->m_ml);
53 }
54 
_cpyextfunc_type(LibObject * lib,struct CPyExtFunc_s * exf)55 static PyObject *_cpyextfunc_type(LibObject *lib, struct CPyExtFunc_s *exf)
56 {
57     PyObject *tuple, *result;
58     tuple = realize_c_type_or_func(lib->l_types_builder,
59                                    lib->l_types_builder->ctx.types,
60                                    exf->type_index);
61     if (tuple == NULL)
62         return NULL;
63 
64     /* 'tuple' is a tuple of length 1 containing the real CT_FUNCTIONPTR
65        object */
66     result = PyTuple_GetItem(tuple, 0);
67     Py_XINCREF(result);
68     Py_DECREF(tuple);
69     return result;
70 }
71 
_cpyextfunc_type_index(PyObject * x)72 static PyObject *_cpyextfunc_type_index(PyObject *x)
73 {
74     struct CPyExtFunc_s *exf;
75     LibObject *lib;
76 
77     assert(PyErr_Occurred());
78     exf = _cpyextfunc_get(x);
79     if (exf == NULL)
80         return NULL;    /* still the same exception is set */
81 
82     PyErr_Clear();
83 
84     lib = (LibObject *)PyCFunction_GET_SELF(x);
85     return _cpyextfunc_type(lib, exf);
86 }
87 
88 static void cdlopen_close_ignore_errors(void *libhandle);  /* forward */
89 static void *cdlopen_fetch(PyObject *libname, void *libhandle,
90                            const char *symbol);
91 
lib_dealloc(LibObject * lib)92 static void lib_dealloc(LibObject *lib)
93 {
94     PyObject_GC_UnTrack(lib);
95     if (lib->l_auto_close)
96         cdlopen_close_ignore_errors(lib->l_libhandle);
97     Py_DECREF(lib->l_dict);
98     Py_DECREF(lib->l_libname);
99     Py_DECREF(lib->l_ffi);
100     PyObject_GC_Del(lib);
101 }
102 
lib_traverse(LibObject * lib,visitproc visit,void * arg)103 static int lib_traverse(LibObject *lib, visitproc visit, void *arg)
104 {
105     Py_VISIT(lib->l_dict);
106     Py_VISIT(lib->l_libname);
107     Py_VISIT(lib->l_ffi);
108     return 0;
109 }
110 
lib_repr(LibObject * lib)111 static PyObject *lib_repr(LibObject *lib)
112 {
113     return PyText_FromFormat("<Lib object for '%.200s'>",
114                              PyText_AS_UTF8(lib->l_libname));
115 }
116 
lib_build_cpython_func(LibObject * lib,const struct _cffi_global_s * g,const char * s,int flags)117 static PyObject *lib_build_cpython_func(LibObject *lib,
118                                         const struct _cffi_global_s *g,
119                                         const char *s, int flags)
120 {
121     /* First make sure the argument types and return type are really
122        built.  The C extension code can then assume that they are,
123        by calling _cffi_type().
124     */
125     PyObject *result = NULL;
126     CTypeDescrObject **pfargs = NULL;
127     CTypeDescrObject *fresult;
128     Py_ssize_t nargs = 0;
129     struct CPyExtFunc_s *xfunc;
130     int i, type_index = _CFFI_GETARG(g->type_op);
131     _cffi_opcode_t *opcodes = lib->l_types_builder->ctx.types;
132     static const char *const format = ";\n\nCFFI C function from %s.lib";
133     const char *libname = PyText_AS_UTF8(lib->l_libname);
134     struct funcbuilder_s funcbuilder;
135 
136     /* return type: */
137     fresult = realize_c_func_return_type(lib->l_types_builder, opcodes,
138                                        type_index);
139     if (fresult == NULL)
140         goto error;
141 
142     /* argument types: */
143     /* note that if the arguments are already built, they have a
144        pointer in the 'opcodes' array, and GETOP() returns a
145        random even value.  But OP_FUNCTION_END is odd, so the
146        condition below still works correctly. */
147     i = type_index + 1;
148     while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END)
149         i++;
150     pfargs = alloca(sizeof(CTypeDescrObject *) * (i - type_index - 1));
151     i = type_index + 1;
152     while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END) {
153         CTypeDescrObject *ct = realize_c_type(lib->l_types_builder, opcodes, i);
154         if (ct == NULL)
155             goto error;
156         pfargs[nargs++] = ct;
157         i++;
158     }
159 
160     memset(&funcbuilder, 0, sizeof(funcbuilder));
161     if (fb_build_name(&funcbuilder, g->name, pfargs, nargs, fresult, 0) < 0)
162         goto error;
163 
164     /* The few bytes of memory we allocate here appear to leak, but
165        this is not a real leak.  Indeed, CPython never unloads its C
166        extension modules.  There is only one PyMem_Malloc() per real
167        C function in a CFFI C extension module.  That means that this
168        PyMem_Malloc() could also have been written with a static
169        global variable generated for each CPYTHON_BLTN defined in the
170        C extension, and the effect would be the same (but a bit more
171        complicated).
172     */
173     xfunc = PyMem_Malloc(sizeof(struct CPyExtFunc_s) +
174                          funcbuilder.nb_bytes +
175                          strlen(format) + strlen(libname));
176     if (xfunc == NULL) {
177         PyErr_NoMemory();
178         goto error;
179     }
180     memset((char *)xfunc, 0, sizeof(struct CPyExtFunc_s));
181     assert(g->address);
182     xfunc->md.ml_meth = (PyCFunction)g->address;
183     xfunc->md.ml_flags = flags;
184     xfunc->md.ml_name = g->name;
185     xfunc->md.ml_doc = xfunc->doc;
186     xfunc->direct_fn = g->size_or_direct_fn;
187     xfunc->type_index = type_index;
188 
189     /* build the docstring */
190     funcbuilder.bufferp = xfunc->doc;
191     if (fb_build_name(&funcbuilder, g->name, pfargs, nargs, fresult, 0) < 0)
192         goto error;
193     sprintf(funcbuilder.bufferp - 1, format, libname);
194     /* done building the docstring */
195 
196     result = PyCFunction_NewEx(&xfunc->md, (PyObject *)lib, lib->l_libname);
197     /* fall-through */
198  error:
199     Py_XDECREF(fresult);
200     while (nargs > 0) {
201         --nargs;
202         Py_DECREF(pfargs[nargs]);
203     }
204     return result;
205 }
206 
lib_build_and_cache_attr(LibObject * lib,PyObject * name,int recursion)207 static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name,
208                                           int recursion)
209 {
210     /* does not return a new reference! */
211     PyObject *x;
212     int index;
213     const struct _cffi_global_s *g;
214     CTypeDescrObject *ct;
215     builder_c_t *types_builder = lib->l_types_builder;
216     const char *s = PyText_AsUTF8(name);
217     if (s == NULL)
218         return NULL;
219 
220     index = search_in_globals(&types_builder->ctx, s, strlen(s));
221     if (index < 0) {
222 
223         if (types_builder->included_libs != NULL) {
224             Py_ssize_t i;
225             PyObject *included_ffis = types_builder->included_ffis;
226             PyObject *included_libs = types_builder->included_libs;
227 
228             if (recursion > 100) {
229                 PyErr_SetString(PyExc_RuntimeError,
230                     "recursion overflow in ffi.include() delegations");
231                 return NULL;
232             }
233 
234             for (i = 0; i < PyTuple_GET_SIZE(included_libs); i++) {
235                 LibObject *lib1;
236 
237                 lib1 = (LibObject *)PyTuple_GET_ITEM(included_libs, i);
238                 if (lib1 != NULL) {
239                     x = PyDict_GetItem(lib1->l_dict, name);
240                     if (x != NULL) {
241                         Py_INCREF(x);
242                         goto found;
243                     }
244                     x = lib_build_and_cache_attr(lib1, name, recursion + 1);
245                     if (x != NULL) {
246                         Py_INCREF(x);
247                         goto found;
248                     }
249                 }
250                 else {
251                     FFIObject *ffi1;
252 
253                     ffi1 = (FFIObject *)PyTuple_GetItem(included_ffis, i);
254                     if (ffi1 == NULL)
255                         return NULL;
256                     x = ffi_fetch_int_constant(ffi1, s, recursion + 1);
257                     if (x != NULL)
258                         goto found;
259                 }
260                 if (PyErr_Occurred())
261                     return NULL;
262             }
263         }
264 
265         if (recursion > 0)
266             return NULL;  /* no error set, continue looking elsewhere */
267 
268         PyErr_Format(PyExc_AttributeError,
269                      "cffi library '%.200s' has no function, constant "
270                      "or global variable named '%.200s'",
271                      PyText_AS_UTF8(lib->l_libname), s);
272         return NULL;
273     }
274 
275     g = &types_builder->ctx.globals[index];
276 
277     switch (_CFFI_GETOP(g->type_op)) {
278 
279     case _CFFI_OP_CPYTHON_BLTN_V:
280         x = lib_build_cpython_func(lib, g, s, METH_VARARGS);
281         break;
282 
283     case _CFFI_OP_CPYTHON_BLTN_N:
284         x = lib_build_cpython_func(lib, g, s, METH_NOARGS);
285         break;
286 
287     case _CFFI_OP_CPYTHON_BLTN_O:
288         x = lib_build_cpython_func(lib, g, s, METH_O);
289         break;
290 
291     case _CFFI_OP_CONSTANT_INT:
292     case _CFFI_OP_ENUM:
293     {
294         /* a constant integer whose value, in an "unsigned long long",
295            is obtained by calling the function at g->address */
296         x = realize_global_int(types_builder, index);
297         break;
298     }
299 
300     case _CFFI_OP_CONSTANT:
301     case _CFFI_OP_DLOPEN_CONST:
302     {
303         /* a constant which is not of integer type */
304         char *data;
305         ct = realize_c_type(types_builder, types_builder->ctx.types,
306                             _CFFI_GETARG(g->type_op));
307         if (ct == NULL)
308             return NULL;
309 
310         if (ct->ct_size <= 0) {
311             PyErr_Format(FFIError, "constant '%s' is of type '%s', "
312                          "whose size is not known", s, ct->ct_name);
313             return NULL;
314         }
315         if (g->address == NULL) {
316             /* for dlopen() style */
317             assert(_CFFI_GETOP(g->type_op) == _CFFI_OP_DLOPEN_CONST);
318             data = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
319             if (data == NULL)
320                 return NULL;
321         }
322         else {
323             /* The few bytes of memory we allocate here appear to leak, but
324                this is not a real leak.  Indeed, CPython never unloads its C
325                extension modules.  There is only one PyMem_Malloc() per real
326                non-integer C constant in a CFFI C extension module.  That
327                means that this PyMem_Malloc() could also have been written
328                with a static global variable generated for each OP_CONSTANT
329                defined in the C extension, and the effect would be the same
330                (but a bit more complicated).
331 
332                Note that we used to do alloca(), but see issue #198.  We
333                could still do alloca(), or explicit PyMem_Free(), in some
334                cases; but there is no point and it only makes the remaining
335                less-common cases more suspicious.
336             */
337             assert(_CFFI_GETOP(g->type_op) == _CFFI_OP_CONSTANT);
338             data = PyMem_Malloc(ct->ct_size);
339             if (data == NULL) {
340                 PyErr_NoMemory();
341                 return NULL;
342             }
343             ((void(*)(char*))g->address)(data);
344         }
345         x = convert_to_object(data, ct);
346         Py_DECREF(ct);
347         break;
348     }
349 
350     case _CFFI_OP_GLOBAL_VAR:
351     {
352         /* global variable of the exact type specified here
353            (nowadays, only used by the ABI mode or backward
354            compatibility; see _CFFI_OP_GLOBAL_VAR_F for the API mode)
355          */
356         Py_ssize_t g_size = (Py_ssize_t)g->size_or_direct_fn;
357         ct = realize_c_type(types_builder, types_builder->ctx.types,
358                             _CFFI_GETARG(g->type_op));
359         if (ct == NULL)
360             return NULL;
361         if (g_size != ct->ct_size && g_size != 0 && ct->ct_size > 0) {
362             PyErr_Format(FFIError,
363                          "global variable '%.200s' should be %zd bytes "
364                          "according to the cdef, but is actually %zd",
365                          s, ct->ct_size, g_size);
366             x = NULL;
367         }
368         else {
369             void *address = g->address;
370             if (address == NULL) {
371                 /* for dlopen() style */
372                 address = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
373                 if (address == NULL)
374                     return NULL;
375             }
376             x = make_global_var(name, ct, address, NULL);
377         }
378         Py_DECREF(ct);
379         break;
380     }
381 
382     case _CFFI_OP_GLOBAL_VAR_F:
383         ct = realize_c_type(types_builder, types_builder->ctx.types,
384                             _CFFI_GETARG(g->type_op));
385         if (ct == NULL)
386             return NULL;
387         x = make_global_var(name, ct, NULL, (gs_fetch_addr_fn)g->address);
388         Py_DECREF(ct);
389         break;
390 
391     case _CFFI_OP_DLOPEN_FUNC:
392     {
393         /* For dlopen(): the function of the given 'name'.  We use
394            dlsym() to get the address of something in the dynamic
395            library, which we interpret as being exactly a function of
396            the specified type.
397         */
398         PyObject *ct1;
399         void *address = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
400         if (address == NULL)
401             return NULL;
402 
403         ct1 = realize_c_type_or_func(types_builder,
404                                      types_builder->ctx.types,
405                                      _CFFI_GETARG(g->type_op));
406         if (ct1 == NULL)
407             return NULL;
408 
409         assert(!CTypeDescr_Check(ct1));   /* must be a function */
410         x = new_simple_cdata(address, unwrap_fn_as_fnptr(ct1));
411 
412         Py_DECREF(ct1);
413         break;
414     }
415 
416     case _CFFI_OP_EXTERN_PYTHON:
417         /* for reading 'lib.bar' where bar is declared with extern "Python" */
418         ct = realize_c_type(types_builder, types_builder->ctx.types,
419                             _CFFI_GETARG(g->type_op));
420         if (ct == NULL)
421             return NULL;
422         x = convert_to_object((char *)&g->size_or_direct_fn, ct);
423         Py_DECREF(ct);
424         break;
425 
426     default:
427         PyErr_Format(PyExc_NotImplementedError, "in lib_build_attr: op=%d",
428                      (int)_CFFI_GETOP(g->type_op));
429         return NULL;
430     }
431 
432  found:
433     if (x != NULL) {
434         int err = PyDict_SetItem(lib->l_dict, name, x);
435         Py_DECREF(x);
436         if (err < 0)     /* else there is still one ref left in the dict */
437             return NULL;
438     }
439     return x;
440 }
441 
442 #define LIB_GET_OR_CACHE_ADDR(x, lib, name, error)      \
443     do {                                                \
444         x = PyDict_GetItem(lib->l_dict, name);          \
445         if (x == NULL) {                                \
446             x = lib_build_and_cache_attr(lib, name, 0); \
447             if (x == NULL) {                            \
448                 error;                                  \
449             }                                           \
450         }                                               \
451     } while (0)
452 
_lib_dir1(LibObject * lib,int ignore_global_vars)453 static PyObject *_lib_dir1(LibObject *lib, int ignore_global_vars)
454 {
455     const struct _cffi_global_s *g = lib->l_types_builder->ctx.globals;
456     int i, count = 0, total = lib->l_types_builder->ctx.num_globals;
457     PyObject *s, *lst = PyList_New(total);
458     if (lst == NULL)
459         return NULL;
460 
461     for (i = 0; i < total; i++) {
462         if (ignore_global_vars) {
463             int op = _CFFI_GETOP(g[i].type_op);
464             if (op == _CFFI_OP_GLOBAL_VAR || op == _CFFI_OP_GLOBAL_VAR_F)
465                 continue;
466         }
467         s = PyText_FromString(g[i].name);
468         if (s == NULL)
469             goto error;
470         PyList_SET_ITEM(lst, count, s);
471         count++;
472     }
473     if (PyList_SetSlice(lst, count, total, NULL) < 0)
474         goto error;
475     return lst;
476 
477  error:
478     Py_DECREF(lst);
479     return NULL;
480 }
481 
_lib_dict(LibObject * lib)482 static PyObject *_lib_dict(LibObject *lib)
483 {
484     const struct _cffi_global_s *g = lib->l_types_builder->ctx.globals;
485     int i, total = lib->l_types_builder->ctx.num_globals;
486     PyObject *name, *x, *d = PyDict_New();
487     if (d == NULL)
488         return NULL;
489 
490     for (i = 0; i < total; i++) {
491         name = PyText_FromString(g[i].name);
492         if (name == NULL)
493             goto error;
494 
495         LIB_GET_OR_CACHE_ADDR(x, lib, name, goto error);
496 
497         if (PyDict_SetItem(d, name, x) < 0)
498             goto error;
499         Py_DECREF(name);
500     }
501     return d;
502 
503  error:
504     Py_XDECREF(name);
505     Py_DECREF(d);
506     return NULL;
507 }
508 
lib_getattr(LibObject * lib,PyObject * name)509 static PyObject *lib_getattr(LibObject *lib, PyObject *name)
510 {
511     const char *p;
512     PyObject *x;
513     LIB_GET_OR_CACHE_ADDR(x, lib, name, goto missing);
514 
515     if (GlobSupport_Check(x)) {
516         return read_global_var((GlobSupportObject *)x);
517     }
518     Py_INCREF(x);
519     return x;
520 
521  missing:
522     /*** ATTRIBUTEERROR IS SET HERE ***/
523     p = PyText_AsUTF8(name);
524     if (p == NULL)
525         return NULL;
526     if (strcmp(p, "__all__") == 0) {
527         PyErr_Clear();
528         return _lib_dir1(lib, 1);
529     }
530     if (strcmp(p, "__dict__") == 0) {
531         PyErr_Clear();
532         return _lib_dict(lib);
533     }
534     if (strcmp(p, "__class__") == 0) {
535         PyErr_Clear();
536         x = (PyObject *)&PyModule_Type;
537         /* ^^^ used to be Py_TYPE(lib).  But HAAAAAACK!  That makes
538            help() behave correctly.  I couldn't find a more reasonable
539            way.  Urgh. */
540         Py_INCREF(x);
541         return x;
542     }
543     /* this hack is for Python 3.5, and also to give a more
544        module-like behavior */
545     if (strcmp(p, "__name__") == 0) {
546         PyErr_Clear();
547         return PyText_FromFormat("%s.lib", PyText_AS_UTF8(lib->l_libname));
548     }
549 #if PY_MAJOR_VERSION >= 3
550     if (strcmp(p, "__loader__") == 0 || strcmp(p, "__spec__") == 0) {
551         /* some more module-like behavior hacks */
552         PyErr_Clear();
553         Py_INCREF(Py_None);
554         return Py_None;
555     }
556 #endif
557     return NULL;
558 }
559 
lib_setattr(LibObject * lib,PyObject * name,PyObject * val)560 static int lib_setattr(LibObject *lib, PyObject *name, PyObject *val)
561 {
562     PyObject *x;
563     LIB_GET_OR_CACHE_ADDR(x, lib, name, return -1);
564 
565     if (val == NULL) {
566         PyErr_SetString(PyExc_AttributeError, "C attribute cannot be deleted");
567         return -1;
568     }
569 
570     if (GlobSupport_Check(x)) {
571         return write_global_var((GlobSupportObject *)x, val);
572     }
573 
574     PyErr_Format(PyExc_AttributeError,
575                  "cannot write to function or constant '%.200s'",
576                  PyText_Check(name) ? PyText_AS_UTF8(name) : "?");
577     return -1;
578 }
579 
lib_dir(PyObject * self,PyObject * noarg)580 static PyObject *lib_dir(PyObject *self, PyObject *noarg)
581 {
582     return _lib_dir1((LibObject *)self, 0);
583 }
584 
585 static PyMethodDef lib_methods[] = {
586     {"__dir__",   lib_dir,  METH_NOARGS},
587     {NULL,        NULL}           /* sentinel */
588 };
589 
590 static PyTypeObject Lib_Type = {
591     PyVarObject_HEAD_INIT(NULL, 0)
592     "_cffi_backend.Lib",
593     sizeof(LibObject),
594     0,
595     (destructor)lib_dealloc,                    /* tp_dealloc */
596     0,                                          /* tp_print */
597     0,                                          /* tp_getattr */
598     0,                                          /* tp_setattr */
599     0,                                          /* tp_compare */
600     (reprfunc)lib_repr,                         /* tp_repr */
601     0,                                          /* tp_as_number */
602     0,                                          /* tp_as_sequence */
603     0,                                          /* tp_as_mapping */
604     0,                                          /* tp_hash */
605     0,                                          /* tp_call */
606     0,                                          /* tp_str */
607     (getattrofunc)lib_getattr,                  /* tp_getattro */
608     (setattrofunc)lib_setattr,                  /* tp_setattro */
609     0,                                          /* tp_as_buffer */
610     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
611     0,                                          /* tp_doc */
612     (traverseproc)lib_traverse,                 /* tp_traverse */
613     0,                                          /* tp_clear */
614     0,                                          /* tp_richcompare */
615     0,                                          /* tp_weaklistoffset */
616     0,                                          /* tp_iter */
617     0,                                          /* tp_iternext */
618     lib_methods,                                /* tp_methods */
619     0,                                          /* tp_members */
620     0,                                          /* tp_getset */
621     0,                                          /* tp_base */
622     0,                                          /* tp_dict */
623     0,                                          /* tp_descr_get */
624     0,                                          /* tp_descr_set */
625     offsetof(LibObject, l_dict),                /* tp_dictoffset */
626 };
627 
lib_internal_new(FFIObject * ffi,const char * module_name,void * dlopen_libhandle,int auto_close)628 static LibObject *lib_internal_new(FFIObject *ffi, const char *module_name,
629                                    void *dlopen_libhandle, int auto_close)
630 {
631     LibObject *lib;
632     PyObject *libname, *dict;
633 
634     libname = PyText_FromString(module_name);
635     if (libname == NULL)
636         goto err1;
637 
638     dict = PyDict_New();
639     if (dict == NULL)
640         goto err2;
641 
642     lib = (LibObject *)PyType_GenericAlloc(&Lib_Type, 0);
643     if (lib == NULL)
644         goto err3;
645 
646     lib->l_types_builder = &ffi->types_builder;
647     lib->l_dict = dict;
648     lib->l_libname = libname;
649     Py_INCREF(ffi);
650     lib->l_ffi = ffi;
651     lib->l_libhandle = dlopen_libhandle;
652     lib->l_auto_close = auto_close;
653     return lib;
654 
655  err3:
656     Py_DECREF(dict);
657  err2:
658     Py_DECREF(libname);
659  err1:
660     if (auto_close)
661         cdlopen_close_ignore_errors(dlopen_libhandle);
662     return NULL;
663 }
664 
address_of_global_var(PyObject * args)665 static PyObject *address_of_global_var(PyObject *args)
666 {
667     LibObject *lib;
668     PyObject *x, *o_varname;
669     char *varname;
670 
671     if (!PyArg_ParseTuple(args, "O!s", &Lib_Type, &lib, &varname))
672         return NULL;
673 
674     /* rebuild a string from 'varname', to do typechecks and to force
675        a unicode back to a plain string (on python 2) */
676     o_varname = PyText_FromString(varname);
677     if (o_varname == NULL)
678         return NULL;
679 
680     LIB_GET_OR_CACHE_ADDR(x, lib, o_varname, goto error);
681     Py_DECREF(o_varname);
682     if (GlobSupport_Check(x)) {
683         return cg_addressof_global_var((GlobSupportObject *)x);
684     }
685     else {
686         struct CPyExtFunc_s *exf = _cpyextfunc_get(x);
687         if (exf != NULL) {  /* an OP_CPYTHON_BLTN: '&func' returns a cdata */
688             PyObject *ct;
689             if (exf->direct_fn == NULL) {
690                 Py_INCREF(x);    /* backward compatibility */
691                 return x;
692             }
693             ct = _cpyextfunc_type(lib, exf);
694             if (ct == NULL)
695                 return NULL;
696             x = new_simple_cdata(exf->direct_fn, (CTypeDescrObject *)ct);
697             Py_DECREF(ct);
698             return x;
699         }
700         if (CData_Check(x) &&  /* a constant functionptr cdata: 'f == &f' */
701                 (((CDataObject *)x)->c_type->ct_flags & CT_FUNCTIONPTR) != 0) {
702             Py_INCREF(x);
703             return x;
704         }
705         else {
706             PyErr_Format(PyExc_AttributeError,
707                          "cannot take the address of the constant '%.200s'",
708                          varname);
709             return NULL;
710         }
711     }
712 
713  error:
714     Py_DECREF(o_varname);
715     return NULL;
716 }
717