• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* An FFI object has methods like ffi.new().  It is also a container
3    for the type declarations (typedefs and structs) that you can use,
4    say in ffi.new().
5 
6    CTypeDescrObjects are internally stored in the dict 'types_dict'.
7    The types_dict is lazily filled with CTypeDescrObjects made from
8    reading a _cffi_type_context_s structure.
9 
10    In "modern" mode, the FFI instance is made by the C extension
11    module originally created by recompile().  The _cffi_type_context_s
12    structure comes from global data in the C extension module.
13 
14    In "compatibility" mode, an FFI instance is created explicitly by
15    the user, and its _cffi_type_context_s is initially empty.  You
16    need to call ffi.cdef() to add more information to it.
17 */
18 
19 #define FFI_COMPLEXITY_OUTPUT   1200     /* xxx should grow as needed */
20 
21 #define FFIObject_Check(op) PyObject_TypeCheck(op, &FFI_Type)
22 #define LibObject_Check(ob)  ((Py_TYPE(ob) == &Lib_Type))
23 
24 struct FFIObject_s {
25     PyObject_HEAD
26     PyObject *gc_wrefs, *gc_wrefs_freelist;
27     PyObject *init_once_cache;
28     struct _cffi_parse_info_s info;
29     char ctx_is_static, ctx_is_nonempty;
30     builder_c_t types_builder;
31 };
32 
ffi_internal_new(PyTypeObject * ffitype,const struct _cffi_type_context_s * static_ctx)33 static FFIObject *ffi_internal_new(PyTypeObject *ffitype,
34                                  const struct _cffi_type_context_s *static_ctx)
35 {
36     static _cffi_opcode_t internal_output[FFI_COMPLEXITY_OUTPUT];
37 
38     FFIObject *ffi;
39     if (static_ctx != NULL) {
40         ffi = (FFIObject *)PyObject_GC_New(FFIObject, ffitype);
41         /* we don't call PyObject_GC_Track() here: from _cffi_init_module()
42            it is not needed, because in this case the ffi object is immortal */
43     }
44     else {
45         ffi = (FFIObject *)ffitype->tp_alloc(ffitype, 0);
46     }
47     if (ffi == NULL)
48         return NULL;
49 
50     if (init_builder_c(&ffi->types_builder, static_ctx) < 0) {
51         Py_DECREF(ffi);
52         return NULL;
53     }
54     ffi->gc_wrefs = NULL;
55     ffi->gc_wrefs_freelist = NULL;
56     ffi->init_once_cache = NULL;
57     ffi->info.ctx = &ffi->types_builder.ctx;
58     ffi->info.output = internal_output;
59     ffi->info.output_size = FFI_COMPLEXITY_OUTPUT;
60     ffi->ctx_is_static = (static_ctx != NULL);
61     ffi->ctx_is_nonempty = (static_ctx != NULL);
62     return ffi;
63 }
64 
ffi_dealloc(FFIObject * ffi)65 static void ffi_dealloc(FFIObject *ffi)
66 {
67     PyObject_GC_UnTrack(ffi);
68     Py_XDECREF(ffi->gc_wrefs);
69     Py_XDECREF(ffi->gc_wrefs_freelist);
70     Py_XDECREF(ffi->init_once_cache);
71 
72     free_builder_c(&ffi->types_builder, ffi->ctx_is_static);
73 
74     Py_TYPE(ffi)->tp_free((PyObject *)ffi);
75 }
76 
ffi_traverse(FFIObject * ffi,visitproc visit,void * arg)77 static int ffi_traverse(FFIObject *ffi, visitproc visit, void *arg)
78 {
79     Py_VISIT(ffi->types_builder.types_dict);
80     Py_VISIT(ffi->types_builder.included_ffis);
81     Py_VISIT(ffi->types_builder.included_libs);
82     Py_VISIT(ffi->gc_wrefs);
83     return 0;
84 }
85 
ffiobj_new(PyTypeObject * type,PyObject * args,PyObject * kwds)86 static PyObject *ffiobj_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
87 {
88     /* user-facing initialization code, for explicit FFI() calls */
89     return (PyObject *)ffi_internal_new(type, NULL);
90 }
91 
92 /* forward, declared in cdlopen.c because it's mostly useful for this case */
93 static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds);
94 
ffi_fetch_int_constant(FFIObject * ffi,const char * name,int recursion)95 static PyObject *ffi_fetch_int_constant(FFIObject *ffi, const char *name,
96                                         int recursion)
97 {
98     int index;
99 
100     index = search_in_globals(&ffi->types_builder.ctx, name, strlen(name));
101     if (index >= 0) {
102         const struct _cffi_global_s *g;
103         g = &ffi->types_builder.ctx.globals[index];
104 
105         switch (_CFFI_GETOP(g->type_op)) {
106         case _CFFI_OP_CONSTANT_INT:
107         case _CFFI_OP_ENUM:
108             return realize_global_int(&ffi->types_builder, index);
109 
110         default:
111             PyErr_Format(FFIError,
112                          "function, global variable or non-integer constant "
113                          "'%.200s' must be fetched from its original 'lib' "
114                          "object", name);
115             return NULL;
116         }
117     }
118 
119     if (ffi->types_builder.included_ffis != NULL) {
120         Py_ssize_t i;
121         PyObject *included_ffis = ffi->types_builder.included_ffis;
122 
123         if (recursion > 100) {
124             PyErr_SetString(PyExc_RuntimeError,
125                             "recursion overflow in ffi.include() delegations");
126             return NULL;
127         }
128 
129         for (i = 0; i < PyTuple_GET_SIZE(included_ffis); i++) {
130             FFIObject *ffi1;
131             PyObject *x;
132 
133             ffi1 = (FFIObject *)PyTuple_GET_ITEM(included_ffis, i);
134             x = ffi_fetch_int_constant(ffi1, name, recursion + 1);
135             if (x != NULL || PyErr_Occurred())
136                 return x;
137         }
138     }
139     return NULL;     /* no exception set, means "not found" */
140 }
141 
142 #define ACCEPT_STRING   1
143 #define ACCEPT_CTYPE    2
144 #define ACCEPT_CDATA    4
145 #define ACCEPT_ALL      (ACCEPT_STRING | ACCEPT_CTYPE | ACCEPT_CDATA)
146 #define CONSIDER_FN_AS_FNPTR  8
147 
_ffi_bad_type(FFIObject * ffi,const char * input_text)148 static CTypeDescrObject *_ffi_bad_type(FFIObject *ffi, const char *input_text)
149 {
150     size_t length = strlen(input_text);
151     char *extra;
152 
153     if (length > 500) {
154         extra = "";
155     }
156     else {
157         char *p;
158         size_t i, num_spaces = ffi->info.error_location;
159         extra = alloca(length + num_spaces + 4);
160         p = extra;
161         *p++ = '\n';
162         for (i = 0; i < length; i++) {
163             if (' ' <= input_text[i] && input_text[i] < 0x7f)
164                 *p++ = input_text[i];
165             else if (input_text[i] == '\t' || input_text[i] == '\n')
166                 *p++ = ' ';
167             else
168                 *p++ = '?';
169         }
170         *p++ = '\n';
171         memset(p, ' ', num_spaces);
172         p += num_spaces;
173         *p++ = '^';
174         *p++ = 0;
175     }
176     PyErr_Format(FFIError, "%s%s", ffi->info.error_message, extra);
177     return NULL;
178 }
179 
_ffi_type(FFIObject * ffi,PyObject * arg,int accept)180 static CTypeDescrObject *_ffi_type(FFIObject *ffi, PyObject *arg,
181                                    int accept)
182 {
183     /* Returns the CTypeDescrObject from the user-supplied 'arg'.
184        Does not return a new reference!
185     */
186     if ((accept & ACCEPT_STRING) && PyText_Check(arg)) {
187         PyObject *types_dict = ffi->types_builder.types_dict;
188         PyObject *x = PyDict_GetItem(types_dict, arg);
189 
190         if (x == NULL) {
191             const char *input_text = PyText_AS_UTF8(arg);
192             int err, index = parse_c_type(&ffi->info, input_text);
193             if (index < 0)
194                 return _ffi_bad_type(ffi, input_text);
195 
196             x = realize_c_type_or_func(&ffi->types_builder,
197                                        ffi->info.output, index);
198             if (x == NULL)
199                 return NULL;
200 
201             /* Cache under the name given by 'arg', in addition to the
202                fact that the same ct is probably already cached under
203                its standardized name.  In a few cases, it is not, e.g.
204                if it is a primitive; for the purpose of this function,
205                the important point is the following line, which makes
206                sure that in any case the next _ffi_type() with the same
207                'arg' will succeed early, in PyDict_GetItem() above.
208             */
209             err = PyDict_SetItem(types_dict, arg, x);
210             Py_DECREF(x); /* we know it was written in types_dict (unless out
211                              of mem), so there is at least that ref left */
212             if (err < 0)
213                 return NULL;
214         }
215 
216         if (CTypeDescr_Check(x))
217             return (CTypeDescrObject *)x;
218         else if (accept & CONSIDER_FN_AS_FNPTR)
219             return unwrap_fn_as_fnptr(x);
220         else
221             return unexpected_fn_type(x);
222     }
223     else if ((accept & ACCEPT_CTYPE) && CTypeDescr_Check(arg)) {
224         return (CTypeDescrObject *)arg;
225     }
226     else if ((accept & ACCEPT_CDATA) && CData_Check(arg)) {
227         return ((CDataObject *)arg)->c_type;
228     }
229 #if PY_MAJOR_VERSION < 3
230     else if (PyUnicode_Check(arg)) {
231         CTypeDescrObject *result;
232         arg = PyUnicode_AsASCIIString(arg);
233         if (arg == NULL)
234             return NULL;
235         result = _ffi_type(ffi, arg, accept);
236         Py_DECREF(arg);
237         return result;
238     }
239 #endif
240     else {
241         const char *m1 = (accept & ACCEPT_STRING) ? "string" : "";
242         const char *m2 = (accept & ACCEPT_CTYPE) ? "ctype object" : "";
243         const char *m3 = (accept & ACCEPT_CDATA) ? "cdata object" : "";
244         const char *s12 = (*m1 && (*m2 || *m3)) ? " or " : "";
245         const char *s23 = (*m2 && *m3) ? " or " : "";
246         PyErr_Format(PyExc_TypeError, "expected a %s%s%s%s%s, got '%.200s'",
247                      m1, s12, m2, s23, m3,
248                      Py_TYPE(arg)->tp_name);
249         return NULL;
250     }
251 }
252 
253 PyDoc_STRVAR(ffi_sizeof_doc,
254 "Return the size in bytes of the argument.\n"
255 "It can be a string naming a C type, or a 'cdata' instance.");
256 
ffi_sizeof(FFIObject * self,PyObject * arg)257 static PyObject *ffi_sizeof(FFIObject *self, PyObject *arg)
258 {
259     Py_ssize_t size;
260 
261     if (CData_Check(arg)) {
262         size = direct_sizeof_cdata((CDataObject *)arg);
263     }
264     else {
265         CTypeDescrObject *ct = _ffi_type(self, arg, ACCEPT_ALL);
266         if (ct == NULL)
267             return NULL;
268         size = ct->ct_size;
269         if (size < 0) {
270             PyErr_Format(FFIError, "don't know the size of ctype '%s'",
271                          ct->ct_name);
272             return NULL;
273         }
274     }
275     return PyInt_FromSsize_t(size);
276 }
277 
278 PyDoc_STRVAR(ffi_alignof_doc,
279 "Return the natural alignment size in bytes of the argument.\n"
280 "It can be a string naming a C type, or a 'cdata' instance.");
281 
ffi_alignof(FFIObject * self,PyObject * arg)282 static PyObject *ffi_alignof(FFIObject *self, PyObject *arg)
283 {
284     int align;
285     CTypeDescrObject *ct = _ffi_type(self, arg, ACCEPT_ALL);
286     if (ct == NULL)
287         return NULL;
288 
289     align = get_alignment(ct);
290     if (align < 0)
291         return NULL;
292     return PyInt_FromLong(align);
293 }
294 
295 PyDoc_STRVAR(ffi_typeof_doc,
296 "Parse the C type given as a string and return the\n"
297 "corresponding <ctype> object.\n"
298 "It can also be used on 'cdata' instance to get its C type.");
299 
300 static PyObject *_cpyextfunc_type_index(PyObject *x);  /* forward */
301 
ffi_typeof(FFIObject * self,PyObject * arg)302 static PyObject *ffi_typeof(FFIObject *self, PyObject *arg)
303 {
304     PyObject *x = (PyObject *)_ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CDATA);
305     if (x != NULL) {
306         Py_INCREF(x);
307     }
308     else {
309         x = _cpyextfunc_type_index(arg);
310     }
311     return x;
312 }
313 
314 PyDoc_STRVAR(ffi_new_doc,
315 "Allocate an instance according to the specified C type and return a\n"
316 "pointer to it.  The specified C type must be either a pointer or an\n"
317 "array: ``new('X *')`` allocates an X and returns a pointer to it,\n"
318 "whereas ``new('X[n]')`` allocates an array of n X'es and returns an\n"
319 "array referencing it (which works mostly like a pointer, like in C).\n"
320 "You can also use ``new('X[]', n)`` to allocate an array of a\n"
321 "non-constant length n.\n"
322 "\n"
323 "The memory is initialized following the rules of declaring a global\n"
324 "variable in C: by default it is zero-initialized, but an explicit\n"
325 "initializer can be given which can be used to fill all or part of the\n"
326 "memory.\n"
327 "\n"
328 "When the returned <cdata> object goes out of scope, the memory is\n"
329 "freed.  In other words the returned <cdata> object has ownership of\n"
330 "the value of type 'cdecl' that it points to.  This means that the raw\n"
331 "data can be used as long as this object is kept alive, but must not be\n"
332 "used for a longer time.  Be careful about that when copying the\n"
333 "pointer to the memory somewhere else, e.g. into another structure.");
334 
_ffi_new(FFIObject * self,PyObject * args,PyObject * kwds,const cffi_allocator_t * allocator)335 static PyObject *_ffi_new(FFIObject *self, PyObject *args, PyObject *kwds,
336                           const cffi_allocator_t *allocator)
337 {
338     CTypeDescrObject *ct;
339     PyObject *arg, *init = Py_None;
340     static char *keywords[] = {"cdecl", "init", NULL};
341     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:new", keywords,
342                                      &arg, &init))
343         return NULL;
344 
345     ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE);
346     if (ct == NULL)
347         return NULL;
348 
349     return direct_newp(ct, init, allocator);
350 }
351 
ffi_new(FFIObject * self,PyObject * args,PyObject * kwds)352 static PyObject *ffi_new(FFIObject *self, PyObject *args, PyObject *kwds)
353 {
354     return _ffi_new(self, args, kwds, &default_allocator);
355 }
356 
_ffi_new_with_allocator(PyObject * allocator,PyObject * args,PyObject * kwds)357 static PyObject *_ffi_new_with_allocator(PyObject *allocator, PyObject *args,
358                                          PyObject *kwds)
359 {
360     cffi_allocator_t alloc1;
361     PyObject *my_alloc, *my_free;
362     my_alloc = PyTuple_GET_ITEM(allocator, 1);
363     my_free  = PyTuple_GET_ITEM(allocator, 2);
364     alloc1.ca_alloc = (my_alloc == Py_None ? NULL : my_alloc);
365     alloc1.ca_free  = (my_free  == Py_None ? NULL : my_free);
366     alloc1.ca_dont_clear = (PyTuple_GET_ITEM(allocator, 3) == Py_False);
367 
368     return _ffi_new((FFIObject *)PyTuple_GET_ITEM(allocator, 0),
369                     args, kwds, &alloc1);
370 }
371 
372 PyDoc_STRVAR(ffi_new_allocator_doc,
373 "Return a new allocator, i.e. a function that behaves like ffi.new()\n"
374 "but uses the provided low-level 'alloc' and 'free' functions.\n"
375 "\n"
376 "'alloc' is called with the size as argument.  If it returns NULL, a\n"
377 "MemoryError is raised.  'free' is called with the result of 'alloc'\n"
378 "as argument.  Both can be either Python functions or directly C\n"
379 "functions.  If 'free' is None, then no free function is called.\n"
380 "If both 'alloc' and 'free' are None, the default is used.\n"
381 "\n"
382 "If 'should_clear_after_alloc' is set to False, then the memory\n"
383 "returned by 'alloc' is assumed to be already cleared (or you are\n"
384 "fine with garbage); otherwise CFFI will clear it.");
385 
ffi_new_allocator(FFIObject * self,PyObject * args,PyObject * kwds)386 static PyObject *ffi_new_allocator(FFIObject *self, PyObject *args,
387                                    PyObject *kwds)
388 {
389     PyObject *allocator, *result;
390     PyObject *my_alloc = Py_None, *my_free = Py_None;
391     int should_clear_after_alloc = 1;
392     static char *keywords[] = {"alloc", "free", "should_clear_after_alloc",
393                                NULL};
394     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi:new_allocator", keywords,
395                                      &my_alloc, &my_free,
396                                      &should_clear_after_alloc))
397         return NULL;
398 
399     if (my_alloc == Py_None && my_free != Py_None) {
400         PyErr_SetString(PyExc_TypeError, "cannot pass 'free' without 'alloc'");
401         return NULL;
402     }
403 
404     allocator = PyTuple_Pack(4,
405                              (PyObject *)self,
406                              my_alloc,
407                              my_free,
408                              PyBool_FromLong(should_clear_after_alloc));
409     if (allocator == NULL)
410         return NULL;
411 
412     {
413         static PyMethodDef md = {"allocator",
414                                  (PyCFunction)_ffi_new_with_allocator,
415                                  METH_VARARGS | METH_KEYWORDS};
416         result = PyCFunction_New(&md, allocator);
417     }
418     Py_DECREF(allocator);
419     return result;
420 }
421 
422 PyDoc_STRVAR(ffi_cast_doc,
423 "Similar to a C cast: returns an instance of the named C\n"
424 "type initialized with the given 'source'.  The source is\n"
425 "casted between integers or pointers of any type.");
426 
ffi_cast(FFIObject * self,PyObject * args)427 static PyObject *ffi_cast(FFIObject *self, PyObject *args)
428 {
429     CTypeDescrObject *ct;
430     PyObject *ob, *arg;
431     if (!PyArg_ParseTuple(args, "OO:cast", &arg, &ob))
432         return NULL;
433 
434     ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE);
435     if (ct == NULL)
436         return NULL;
437 
438     return do_cast(ct, ob);
439 }
440 
441 PyDoc_STRVAR(ffi_string_doc,
442 "Return a Python string (or unicode string) from the 'cdata'.  If\n"
443 "'cdata' is a pointer or array of characters or bytes, returns the\n"
444 "null-terminated string.  The returned string extends until the first\n"
445 "null character, or at most 'maxlen' characters.  If 'cdata' is an\n"
446 "array then 'maxlen' defaults to its length.\n"
447 "\n"
448 "If 'cdata' is a pointer or array of wchar_t, returns a unicode string\n"
449 "following the same rules.\n"
450 "\n"
451 "If 'cdata' is a single character or byte or a wchar_t, returns it as a\n"
452 "string or unicode string.\n"
453 "\n"
454 "If 'cdata' is an enum, returns the value of the enumerator as a\n"
455 "string, or 'NUMBER' if the value is out of range.");
456 
457 #define ffi_string  b_string     /* ffi_string() => b_string()
458                                     from _cffi_backend.c */
459 
460 PyDoc_STRVAR(ffi_unpack_doc,
461 "Unpack an array of C data of the given length,\n"
462 "returning a Python string/unicode/list.\n"
463 "\n"
464 "If 'cdata' is a pointer to 'char', returns a byte string.\n"
465 "It does not stop at the first null.  This is equivalent to:\n"
466 "ffi.buffer(cdata, length)[:]\n"
467 "\n"
468 "If 'cdata' is a pointer to 'wchar_t', returns a unicode string.\n"
469 "'length' is measured in wchar_t's; it is not the size in bytes.\n"
470 "\n"
471 "If 'cdata' is a pointer to anything else, returns a list of\n"
472 "'length' items.  This is a faster equivalent to:\n"
473 "[cdata[i] for i in range(length)]");
474 
475 #define ffi_unpack  b_unpack     /* ffi_unpack() => b_unpack()
476                                     from _cffi_backend.c */
477 
478 
479 PyDoc_STRVAR(ffi_offsetof_doc,
480 "Return the offset of the named field inside the given structure or\n"
481 "array, which must be given as a C type name.  You can give several\n"
482 "field names in case of nested structures.  You can also give numeric\n"
483 "values which correspond to array items, in case of an array type.");
484 
ffi_offsetof(FFIObject * self,PyObject * args)485 static PyObject *ffi_offsetof(FFIObject *self, PyObject *args)
486 {
487     PyObject *arg;
488     CTypeDescrObject *ct;
489     Py_ssize_t i, offset;
490 
491     if (PyTuple_Size(args) < 2) {
492         PyErr_SetString(PyExc_TypeError,
493                         "offsetof() expects at least 2 arguments");
494         return NULL;
495     }
496 
497     arg = PyTuple_GET_ITEM(args, 0);
498     ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE);
499     if (ct == NULL)
500         return NULL;
501 
502     offset = 0;
503     for (i = 1; i < PyTuple_GET_SIZE(args); i++) {
504         Py_ssize_t ofs1;
505         ct = direct_typeoffsetof(ct, PyTuple_GET_ITEM(args, i), i > 1, &ofs1);
506         if (ct == NULL)
507             return NULL;
508         offset += ofs1;
509     }
510     return PyInt_FromSsize_t(offset);
511 }
512 
513 PyDoc_STRVAR(ffi_addressof_doc,
514 "Limited equivalent to the '&' operator in C:\n"
515 "\n"
516 "1. ffi.addressof(<cdata 'struct-or-union'>) returns a cdata that is a\n"
517 "pointer to this struct or union.\n"
518 "\n"
519 "2. ffi.addressof(<cdata>, field-or-index...) returns the address of a\n"
520 "field or array item inside the given structure or array, recursively\n"
521 "in case of nested structures or arrays.\n"
522 "\n"
523 "3. ffi.addressof(<library>, \"name\") returns the address of the named\n"
524 "function or global variable.");
525 
526 static PyObject *address_of_global_var(PyObject *args);  /* forward */
527 
ffi_addressof(FFIObject * self,PyObject * args)528 static PyObject *ffi_addressof(FFIObject *self, PyObject *args)
529 {
530     PyObject *arg, *z, *result;
531     CTypeDescrObject *ct;
532     Py_ssize_t i, offset = 0;
533     int accepted_flags;
534 
535     if (PyTuple_Size(args) < 1) {
536         PyErr_SetString(PyExc_TypeError,
537                         "addressof() expects at least 1 argument");
538         return NULL;
539     }
540 
541     arg = PyTuple_GET_ITEM(args, 0);
542     if (LibObject_Check(arg)) {
543         /* case 3 in the docstring */
544         return address_of_global_var(args);
545     }
546 
547     ct = _ffi_type(self, arg, ACCEPT_CDATA);
548     if (ct == NULL)
549         return NULL;
550 
551     if (PyTuple_GET_SIZE(args) == 1) {
552         /* case 1 in the docstring */
553         accepted_flags = CT_STRUCT | CT_UNION | CT_ARRAY;
554         if ((ct->ct_flags & accepted_flags) == 0) {
555             PyErr_SetString(PyExc_TypeError,
556                             "expected a cdata struct/union/array object");
557             return NULL;
558         }
559     }
560     else {
561         /* case 2 in the docstring */
562         accepted_flags = CT_STRUCT | CT_UNION | CT_ARRAY | CT_POINTER;
563         if ((ct->ct_flags & accepted_flags) == 0) {
564             PyErr_SetString(PyExc_TypeError,
565                         "expected a cdata struct/union/array/pointer object");
566             return NULL;
567         }
568         for (i = 1; i < PyTuple_GET_SIZE(args); i++) {
569             Py_ssize_t ofs1;
570             ct = direct_typeoffsetof(ct, PyTuple_GET_ITEM(args, i),
571                                      i > 1, &ofs1);
572             if (ct == NULL)
573                 return NULL;
574             offset += ofs1;
575         }
576     }
577 
578     z = new_pointer_type(ct);
579     if (z == NULL)
580         return NULL;
581 
582     result = new_simple_cdata(((CDataObject *)arg)->c_data + offset,
583                               (CTypeDescrObject *)z);
584     Py_DECREF(z);
585     return result;
586 }
587 
_combine_type_name_l(CTypeDescrObject * ct,size_t extra_text_len)588 static PyObject *_combine_type_name_l(CTypeDescrObject *ct,
589                                       size_t extra_text_len)
590 {
591     size_t base_name_len;
592     PyObject *result;
593     char *p;
594 
595     base_name_len = strlen(ct->ct_name);
596     result = PyBytes_FromStringAndSize(NULL, base_name_len + extra_text_len);
597     if (result == NULL)
598         return NULL;
599 
600     p = PyBytes_AS_STRING(result);
601     memcpy(p, ct->ct_name, ct->ct_name_position);
602     p += ct->ct_name_position;
603     p += extra_text_len;
604     memcpy(p, ct->ct_name + ct->ct_name_position,
605            base_name_len - ct->ct_name_position);
606     return result;
607 }
608 
609 PyDoc_STRVAR(ffi_getctype_doc,
610 "Return a string giving the C type 'cdecl', which may be itself a\n"
611 "string or a <ctype> object.  If 'replace_with' is given, it gives\n"
612 "extra text to append (or insert for more complicated C types), like a\n"
613 "variable name, or '*' to get actually the C type 'pointer-to-cdecl'.");
614 
ffi_getctype(FFIObject * self,PyObject * args,PyObject * kwds)615 static PyObject *ffi_getctype(FFIObject *self, PyObject *args, PyObject *kwds)
616 {
617     PyObject *c_decl, *res;
618     char *p, *replace_with = "";
619     int add_paren, add_space;
620     CTypeDescrObject *ct;
621     size_t replace_with_len;
622     static char *keywords[] = {"cdecl", "replace_with", NULL};
623 #if PY_MAJOR_VERSION >= 3
624     PyObject *u;
625 #endif
626 
627     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s:getctype", keywords,
628                                      &c_decl, &replace_with))
629         return NULL;
630 
631     ct = _ffi_type(self, c_decl, ACCEPT_STRING|ACCEPT_CTYPE);
632     if (ct == NULL)
633         return NULL;
634 
635     while (replace_with[0] != 0 && isspace(replace_with[0]))
636         replace_with++;
637     replace_with_len = strlen(replace_with);
638     while (replace_with_len > 0 && isspace(replace_with[replace_with_len - 1]))
639         replace_with_len--;
640 
641     add_paren = (replace_with[0] == '*' &&
642                  ((ct->ct_flags & CT_ARRAY) != 0));
643     add_space = (!add_paren && replace_with_len > 0 &&
644                  replace_with[0] != '[' && replace_with[0] != '(');
645 
646     res = _combine_type_name_l(ct, replace_with_len + add_space + 2*add_paren);
647     if (res == NULL)
648         return NULL;
649 
650     p = PyBytes_AS_STRING(res) + ct->ct_name_position;
651     if (add_paren)
652         *p++ = '(';
653     if (add_space)
654         *p++ = ' ';
655     memcpy(p, replace_with, replace_with_len);
656     if (add_paren)
657         p[replace_with_len] = ')';
658 
659 #if PY_MAJOR_VERSION >= 3
660     /* bytes -> unicode string */
661     u = PyUnicode_DecodeLatin1(PyBytes_AS_STRING(res),
662                                PyBytes_GET_SIZE(res),
663                                NULL);
664     Py_DECREF(res);
665     res = u;
666 #endif
667 
668     return res;
669 }
670 
671 PyDoc_STRVAR(ffi_new_handle_doc,
672 "Return a non-NULL cdata of type 'void *' that contains an opaque\n"
673 "reference to the argument, which can be any Python object.  To cast it\n"
674 "back to the original object, use from_handle().  You must keep alive\n"
675 "the cdata object returned by new_handle()!");
676 
ffi_new_handle(FFIObject * self,PyObject * arg)677 static PyObject *ffi_new_handle(FFIObject *self, PyObject *arg)
678 {
679     /* g_ct_voidp is equal to <ctype 'void *'> */
680     return newp_handle(g_ct_voidp, arg);
681 }
682 
683 PyDoc_STRVAR(ffi_from_handle_doc,
684 "Cast a 'void *' back to a Python object.  Must be used *only* on the\n"
685 "pointers returned by new_handle(), and *only* as long as the exact\n"
686 "cdata object returned by new_handle() is still alive (somewhere else\n"
687 "in the program).  Failure to follow these rules will crash.");
688 
689 #define ffi_from_handle  b_from_handle   /* ffi_from_handle => b_from_handle
690                                             from _cffi_backend.c */
691 
692 PyDoc_STRVAR(ffi_from_buffer_doc,
693 "Return a <cdata 'char[]'> that points to the data of the given Python\n"
694 "object, which must support the buffer interface.  Note that this is\n"
695 "not meant to be used on the built-in types str or unicode\n"
696 "(you can build 'char[]' arrays explicitly) but only on objects\n"
697 "containing large quantities of raw data in some other format, like\n"
698 "'array.array' or numpy arrays.");
699 
ffi_from_buffer(FFIObject * self,PyObject * args,PyObject * kwds)700 static PyObject *ffi_from_buffer(FFIObject *self, PyObject *args,
701                                  PyObject *kwds)
702 {
703     PyObject *cdecl1, *python_buf = NULL;
704     CTypeDescrObject *ct;
705     int require_writable = 0;
706     static char *keywords[] = {"cdecl", "python_buffer",
707                                "require_writable", NULL};
708 
709     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:from_buffer", keywords,
710                                      &cdecl1, &python_buf, &require_writable))
711         return NULL;
712 
713     if (python_buf == NULL) {
714         python_buf = cdecl1;
715         ct = g_ct_chararray;
716     }
717     else {
718         ct = _ffi_type(self, cdecl1, ACCEPT_STRING|ACCEPT_CTYPE);
719         if (ct == NULL)
720             return NULL;
721     }
722     return direct_from_buffer(ct, python_buf, require_writable);
723 }
724 
725 PyDoc_STRVAR(ffi_gc_doc,
726 "Return a new cdata object that points to the same data.\n"
727 "Later, when this new cdata object is garbage-collected,\n"
728 "'destructor(old_cdata_object)' will be called.\n"
729 "\n"
730 "The optional 'size' gives an estimate of the size, used to\n"
731 "trigger the garbage collection more eagerly.  So far only used\n"
732 "on PyPy.  It tells the GC that the returned object keeps alive\n"
733 "roughly 'size' bytes of external memory.");
734 
735 #define ffi_gc  b_gcp     /* ffi_gc() => b_gcp()
736                              from _cffi_backend.c */
737 
738 PyDoc_STRVAR(ffi_def_extern_doc,
739 "A decorator.  Attaches the decorated Python function to the C code\n"
740 "generated for the 'extern \"Python\"' function of the same name.\n"
741 "Calling the C function will then invoke the Python function.\n"
742 "\n"
743 "Optional arguments: 'name' is the name of the C function, if\n"
744 "different from the Python function; and 'error' and 'onerror'\n"
745 "handle what occurs if the Python function raises an exception\n"
746 "(see the docs for details).");
747 
748 /* forward; see call_python.c */
749 static PyObject *_ffi_def_extern_decorator(PyObject *, PyObject *);
750 
ffi_def_extern(FFIObject * self,PyObject * args,PyObject * kwds)751 static PyObject *ffi_def_extern(FFIObject *self, PyObject *args,
752                                 PyObject *kwds)
753 {
754     static PyMethodDef md = {"def_extern_decorator",
755                              (PyCFunction)_ffi_def_extern_decorator, METH_O};
756     PyObject *name = Py_None, *error = Py_None;
757     PyObject *res, *onerror = Py_None;
758     static char *keywords[] = {"name", "error", "onerror", NULL};
759 
760     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", keywords,
761                                      &name, &error, &onerror))
762         return NULL;
763 
764     args = Py_BuildValue("(OOOO)", (PyObject *)self, name, error, onerror);
765     if (args == NULL)
766         return NULL;
767 
768     res = PyCFunction_New(&md, args);
769     Py_DECREF(args);
770     return res;
771 }
772 
773 PyDoc_STRVAR(ffi_callback_doc,
774 "Return a callback object or a decorator making such a callback object.\n"
775 "'cdecl' must name a C function pointer type.  The callback invokes the\n"
776 "specified 'python_callable' (which may be provided either directly or\n"
777 "via a decorator).  Important: the callback object must be manually\n"
778 "kept alive for as long as the callback may be invoked from the C code.");
779 
_ffi_callback_decorator(PyObject * outer_args,PyObject * fn)780 static PyObject *_ffi_callback_decorator(PyObject *outer_args, PyObject *fn)
781 {
782     PyObject *res, *old;
783 
784     old = PyTuple_GET_ITEM(outer_args, 1);
785     PyTuple_SET_ITEM(outer_args, 1, fn);
786     res = b_callback(NULL, outer_args);
787     PyTuple_SET_ITEM(outer_args, 1, old);
788     return res;
789 }
790 
ffi_callback(FFIObject * self,PyObject * args,PyObject * kwds)791 static PyObject *ffi_callback(FFIObject *self, PyObject *args, PyObject *kwds)
792 {
793     PyObject *c_decl, *python_callable = Py_None, *error = Py_None;
794     PyObject *res, *onerror = Py_None;
795     static char *keywords[] = {"cdecl", "python_callable", "error",
796                                "onerror", NULL};
797 
798     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", keywords,
799                                      &c_decl, &python_callable, &error,
800                                      &onerror))
801         return NULL;
802 
803     c_decl = (PyObject *)_ffi_type(self, c_decl, ACCEPT_STRING | ACCEPT_CTYPE |
804                                                  CONSIDER_FN_AS_FNPTR);
805     if (c_decl == NULL)
806         return NULL;
807 
808     args = Py_BuildValue("(OOOO)", c_decl, python_callable, error, onerror);
809     if (args == NULL)
810         return NULL;
811 
812     if (python_callable != Py_None) {
813         res = b_callback(NULL, args);
814     }
815     else {
816         static PyMethodDef md = {"callback_decorator",
817                                  (PyCFunction)_ffi_callback_decorator, METH_O};
818         res = PyCFunction_New(&md, args);
819     }
820     Py_DECREF(args);
821     return res;
822 }
823 
824 #ifdef MS_WIN32
825 PyDoc_STRVAR(ffi_getwinerror_doc,
826 "Return either the GetLastError() or the error number given by the\n"
827 "optional 'code' argument, as a tuple '(code, message)'.");
828 
829 #define ffi_getwinerror  b_getwinerror  /* ffi_getwinerror() => b_getwinerror()
830                                            from misc_win32.h */
831 #endif
832 
833 PyDoc_STRVAR(ffi_errno_doc, "the value of 'errno' from/to the C calls");
834 
ffi_get_errno(PyObject * self,void * closure)835 static PyObject *ffi_get_errno(PyObject *self, void *closure)
836 {
837     /* xxx maybe think about how to make the saved errno local
838        to an ffi instance */
839     return b_get_errno(NULL, NULL);
840 }
841 
ffi_set_errno(PyObject * self,PyObject * newval,void * closure)842 static int ffi_set_errno(PyObject *self, PyObject *newval, void *closure)
843 {
844     PyObject *x = b_set_errno(NULL, newval);
845     if (x == NULL)
846         return -1;
847     Py_DECREF(x);
848     return 0;
849 }
850 
851 PyDoc_STRVAR(ffi_dlopen_doc,
852 "Load and return a dynamic library identified by 'name'.  The standard\n"
853 "C library can be loaded by passing None.\n"
854 "\n"
855 "Note that functions and types declared with 'ffi.cdef()' are not\n"
856 "linked to a particular library, just like C headers.  In the library\n"
857 "we only look for the actual (untyped) symbols at the time of their\n"
858 "first access.");
859 
860 PyDoc_STRVAR(ffi_dlclose_doc,
861 "Close a library obtained with ffi.dlopen().  After this call, access to\n"
862 "functions or variables from the library will fail (possibly with a\n"
863 "segmentation fault).");
864 
865 static PyObject *ffi_dlopen(PyObject *self, PyObject *args);  /* forward */
866 static PyObject *ffi_dlclose(PyObject *self, PyObject *args);  /* forward */
867 
868 PyDoc_STRVAR(ffi_int_const_doc,
869 "Get the value of an integer constant.\n"
870 "\n"
871 "'ffi.integer_const(\"xxx\")' is equivalent to 'lib.xxx' if xxx names an\n"
872 "integer constant.  The point of this function is limited to use cases\n"
873 "where you have an 'ffi' object but not any associated 'lib' object.");
874 
ffi_int_const(FFIObject * self,PyObject * args,PyObject * kwds)875 static PyObject *ffi_int_const(FFIObject *self, PyObject *args, PyObject *kwds)
876 {
877     char *name;
878     PyObject *x;
879     static char *keywords[] = {"name", NULL};
880 
881     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", keywords, &name))
882         return NULL;
883 
884     x = ffi_fetch_int_constant(self, name, 0);
885 
886     if (x == NULL && !PyErr_Occurred()) {
887         PyErr_Format(PyExc_AttributeError,
888                      "integer constant '%.200s' not found", name);
889     }
890     return x;
891 }
892 
893 PyDoc_STRVAR(ffi_list_types_doc,
894 "Returns the user type names known to this FFI instance.\n"
895 "This returns a tuple containing three lists of names:\n"
896 "(typedef_names, names_of_structs, names_of_unions)");
897 
ffi_list_types(FFIObject * self,PyObject * noargs)898 static PyObject *ffi_list_types(FFIObject *self, PyObject *noargs)
899 {
900     Py_ssize_t i, n1 = self->types_builder.ctx.num_typenames;
901     Py_ssize_t n23 = self->types_builder.ctx.num_struct_unions;
902     PyObject *o, *lst[3] = {NULL, NULL, NULL}, *result = NULL;
903 
904     lst[0] = PyList_New(n1);
905     if (lst[0] == NULL)
906         goto error;
907     lst[1] = PyList_New(0);
908     if (lst[1] == NULL)
909         goto error;
910     lst[2] = PyList_New(0);
911     if (lst[2] == NULL)
912         goto error;
913 
914     for (i = 0; i < n1; i++) {
915         o = PyText_FromString(self->types_builder.ctx.typenames[i].name);
916         if (o == NULL)
917             goto error;
918         PyList_SET_ITEM(lst[0], i, o);
919     }
920 
921     for (i = 0; i < n23; i++) {
922         const struct _cffi_struct_union_s *s;
923         int err, index;
924 
925         s = &self->types_builder.ctx.struct_unions[i];
926         if (s->name[0] == '$')
927             continue;
928 
929         o = PyText_FromString(s->name);
930         if (o == NULL)
931             goto error;
932         index = (s->flags & _CFFI_F_UNION) ? 2 : 1;
933         err = PyList_Append(lst[index], o);
934         Py_DECREF(o);
935         if (err < 0)
936             goto error;
937     }
938     result = PyTuple_Pack(3, lst[0], lst[1], lst[2]);
939     /* fall-through */
940  error:
941     Py_XDECREF(lst[2]);
942     Py_XDECREF(lst[1]);
943     Py_XDECREF(lst[0]);
944     return result;
945 }
946 
947 PyDoc_STRVAR(ffi_memmove_doc,
948 "ffi.memmove(dest, src, n) copies n bytes of memory from src to dest.\n"
949 "\n"
950 "Like the C function memmove(), the memory areas may overlap;\n"
951 "apart from that it behaves like the C function memcpy().\n"
952 "\n"
953 "'src' can be any cdata ptr or array, or any Python buffer object.\n"
954 "'dest' can be any cdata ptr or array, or a writable Python buffer\n"
955 "object.  The size to copy, 'n', is always measured in bytes.\n"
956 "\n"
957 "Unlike other methods, this one supports all Python buffer including\n"
958 "byte strings and bytearrays---but it still does not support\n"
959 "non-contiguous buffers.");
960 
961 #define ffi_memmove  b_memmove     /* ffi_memmove() => b_memmove()
962                                       from _cffi_backend.c */
963 
964 PyDoc_STRVAR(ffi_init_once_doc,
965 "init_once(function, tag): run function() once.  More precisely,\n"
966 "'function()' is called the first time we see a given 'tag'.\n"
967 "\n"
968 "The return value of function() is remembered and returned by the current\n"
969 "and all future init_once() with the same tag.  If init_once() is called\n"
970 "from multiple threads in parallel, all calls block until the execution\n"
971 "of function() is done.  If function() raises an exception, it is\n"
972 "propagated and nothing is cached.");
973 
974 #if PY_MAJOR_VERSION < 3
975 /* PyCapsule_New is redefined to be PyCObject_FromVoidPtr in _cffi_backend,
976    which gives 2.6 compatibility; but the destructor signature is different */
_free_init_once_lock(void * lock)977 static void _free_init_once_lock(void *lock)
978 {
979     PyThread_free_lock((PyThread_type_lock)lock);
980 }
981 #else
_free_init_once_lock(PyObject * capsule)982 static void _free_init_once_lock(PyObject *capsule)
983 {
984     PyThread_type_lock lock;
985     lock = PyCapsule_GetPointer(capsule, "cffi_init_once_lock");
986     if (lock != NULL)
987         PyThread_free_lock(lock);
988 }
989 #endif
990 
ffi_init_once(FFIObject * self,PyObject * args,PyObject * kwds)991 static PyObject *ffi_init_once(FFIObject *self, PyObject *args, PyObject *kwds)
992 {
993     static char *keywords[] = {"func", "tag", NULL};
994     PyObject *cache, *func, *tag, *tup, *res, *x, *lockobj;
995     PyThread_type_lock lock;
996 
997     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", keywords, &func, &tag))
998         return NULL;
999 
1000     /* a lot of fun with reference counting and error checking
1001        in this function */
1002 
1003     /* atomically get or create a new dict (no GIL release) */
1004     cache = self->init_once_cache;
1005     if (cache == NULL) {
1006         cache = PyDict_New();
1007         if (cache == NULL)
1008             return NULL;
1009         self->init_once_cache = cache;
1010     }
1011 
1012     /* get the tuple from cache[tag], or make a new one: (False, lock) */
1013     tup = PyDict_GetItem(cache, tag);
1014     if (tup == NULL) {
1015         lock = PyThread_allocate_lock();
1016         if (lock == NULL)
1017             return NULL;
1018         x = PyCapsule_New(lock, "cffi_init_once_lock", _free_init_once_lock);
1019         if (x == NULL) {
1020             PyThread_free_lock(lock);
1021             return NULL;
1022         }
1023         tup = PyTuple_Pack(2, Py_False, x);
1024         Py_DECREF(x);
1025         if (tup == NULL)
1026             return NULL;
1027         x = tup;
1028 
1029         /* Possible corner case if 'tag' is an object overriding __eq__
1030            in pure Python: the GIL may be released when we are running it.
1031            We really need to call dict.setdefault(). */
1032         tup = PyObject_CallMethod(cache, "setdefault", "OO", tag, x);
1033         Py_DECREF(x);
1034         if (tup == NULL)
1035             return NULL;
1036 
1037         Py_DECREF(tup);   /* there is still a ref inside the dict */
1038     }
1039 
1040     res = PyTuple_GET_ITEM(tup, 1);
1041     Py_INCREF(res);
1042 
1043     if (PyTuple_GET_ITEM(tup, 0) == Py_True) {
1044         /* tup == (True, result): return the result. */
1045         return res;
1046     }
1047 
1048     /* tup == (False, lock) */
1049     lockobj = res;
1050     lock = (PyThread_type_lock)PyCapsule_GetPointer(lockobj,
1051                                                     "cffi_init_once_lock");
1052     if (lock == NULL) {
1053         Py_DECREF(lockobj);
1054         return NULL;
1055     }
1056 
1057     Py_BEGIN_ALLOW_THREADS
1058     PyThread_acquire_lock(lock, WAIT_LOCK);
1059     Py_END_ALLOW_THREADS
1060 
1061     x = PyDict_GetItem(cache, tag);
1062     if (x != NULL && PyTuple_GET_ITEM(x, 0) == Py_True) {
1063         /* the real result was put in the dict while we were waiting
1064            for PyThread_acquire_lock() above */
1065         res = PyTuple_GET_ITEM(x, 1);
1066         Py_INCREF(res);
1067     }
1068     else {
1069         res = PyObject_CallFunction(func, "");
1070         if (res != NULL) {
1071             tup = PyTuple_Pack(2, Py_True, res);
1072             if (tup == NULL || PyDict_SetItem(cache, tag, tup) < 0) {
1073                 Py_XDECREF(tup);
1074                 Py_DECREF(res);
1075                 res = NULL;
1076             }
1077         }
1078     }
1079 
1080     PyThread_release_lock(lock);
1081     Py_DECREF(lockobj);
1082     return res;
1083 }
1084 
1085 PyDoc_STRVAR(ffi_release_doc,
1086 "Release now the resources held by a 'cdata' object from ffi.new(),\n"
1087 "ffi.gc() or ffi.from_buffer().  The cdata object must not be used\n"
1088 "afterwards.\n"
1089 "\n"
1090 "'ffi.release(cdata)' is equivalent to 'cdata.__exit__()'.\n"
1091 "\n"
1092 "Note that on CPython this method has no effect (so far) on objects\n"
1093 "returned by ffi.new(), because the memory is allocated inline with the\n"
1094 "cdata object and cannot be freed independently.  It might be fixed in\n"
1095 "future releases of cffi.");
1096 
1097 #define ffi_release  b_release     /* ffi_release() => b_release()
1098                                       from _cffi_backend.c */
1099 
1100 
1101 #define METH_VKW  (METH_VARARGS | METH_KEYWORDS)
1102 static PyMethodDef ffi_methods[] = {
1103  {"addressof",  (PyCFunction)ffi_addressof,  METH_VARARGS, ffi_addressof_doc},
1104  {"alignof",    (PyCFunction)ffi_alignof,    METH_O,       ffi_alignof_doc},
1105  {"def_extern", (PyCFunction)ffi_def_extern, METH_VKW,     ffi_def_extern_doc},
1106  {"callback",   (PyCFunction)ffi_callback,   METH_VKW,     ffi_callback_doc},
1107  {"cast",       (PyCFunction)ffi_cast,       METH_VARARGS, ffi_cast_doc},
1108  {"dlclose",    (PyCFunction)ffi_dlclose,    METH_VARARGS, ffi_dlclose_doc},
1109  {"dlopen",     (PyCFunction)ffi_dlopen,     METH_VARARGS, ffi_dlopen_doc},
1110  {"from_buffer",(PyCFunction)ffi_from_buffer,METH_VKW,     ffi_from_buffer_doc},
1111  {"from_handle",(PyCFunction)ffi_from_handle,METH_O,       ffi_from_handle_doc},
1112  {"gc",         (PyCFunction)ffi_gc,         METH_VKW,     ffi_gc_doc},
1113  {"getctype",   (PyCFunction)ffi_getctype,   METH_VKW,     ffi_getctype_doc},
1114 #ifdef MS_WIN32
1115  {"getwinerror",(PyCFunction)ffi_getwinerror,METH_VKW,     ffi_getwinerror_doc},
1116 #endif
1117  {"init_once",  (PyCFunction)ffi_init_once,  METH_VKW,     ffi_init_once_doc},
1118  {"integer_const",(PyCFunction)ffi_int_const,METH_VKW,     ffi_int_const_doc},
1119  {"list_types", (PyCFunction)ffi_list_types, METH_NOARGS,  ffi_list_types_doc},
1120  {"memmove",    (PyCFunction)ffi_memmove,    METH_VKW,     ffi_memmove_doc},
1121  {"new",        (PyCFunction)ffi_new,        METH_VKW,     ffi_new_doc},
1122 {"new_allocator",(PyCFunction)ffi_new_allocator,METH_VKW,ffi_new_allocator_doc},
1123  {"new_handle", (PyCFunction)ffi_new_handle, METH_O,       ffi_new_handle_doc},
1124  {"offsetof",   (PyCFunction)ffi_offsetof,   METH_VARARGS, ffi_offsetof_doc},
1125  {"release",    (PyCFunction)ffi_release,    METH_O,       ffi_release_doc},
1126  {"sizeof",     (PyCFunction)ffi_sizeof,     METH_O,       ffi_sizeof_doc},
1127  {"string",     (PyCFunction)ffi_string,     METH_VKW,     ffi_string_doc},
1128  {"typeof",     (PyCFunction)ffi_typeof,     METH_O,       ffi_typeof_doc},
1129  {"unpack",     (PyCFunction)ffi_unpack,     METH_VKW,     ffi_unpack_doc},
1130  {NULL}
1131 };
1132 
1133 static PyGetSetDef ffi_getsets[] = {
1134     {"errno",  ffi_get_errno,  ffi_set_errno,  ffi_errno_doc},
1135     {NULL}
1136 };
1137 
1138 static PyTypeObject FFI_Type = {
1139     PyVarObject_HEAD_INIT(NULL, 0)
1140     "CompiledFFI",
1141     sizeof(FFIObject),
1142     0,
1143     (destructor)ffi_dealloc,                    /* tp_dealloc */
1144     0,                                          /* tp_print */
1145     0,                                          /* tp_getattr */
1146     0,                                          /* tp_setattr */
1147     0,                                          /* tp_compare */
1148     0,                                          /* tp_repr */
1149     0,                                          /* tp_as_number */
1150     0,                                          /* tp_as_sequence */
1151     0,                                          /* tp_as_mapping */
1152     0,                                          /* tp_hash */
1153     0,                                          /* tp_call */
1154     0,                                          /* tp_str */
1155     PyObject_GenericGetAttr,                    /* tp_getattro */
1156     0,                                          /* tp_setattro */
1157     0,                                          /* tp_as_buffer */
1158     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1159         Py_TPFLAGS_BASETYPE,                    /* tp_flags */
1160     0,                                          /* tp_doc */
1161     (traverseproc)ffi_traverse,                 /* tp_traverse */
1162     0,                                          /* tp_clear */
1163     0,                                          /* tp_richcompare */
1164     0,                                          /* tp_weaklistoffset */
1165     0,                                          /* tp_iter */
1166     0,                                          /* tp_iternext */
1167     ffi_methods,                                /* tp_methods */
1168     0,                                          /* tp_members */
1169     ffi_getsets,                                /* tp_getset */
1170     0,                                          /* tp_base */
1171     0,                                          /* tp_dict */
1172     0,                                          /* tp_descr_get */
1173     0,                                          /* tp_descr_set */
1174     0,                                          /* tp_dictoffset */
1175     ffiobj_init,                                /* tp_init */
1176     0,                                          /* tp_alloc */
1177     ffiobj_new,                                 /* tp_new */
1178     PyObject_GC_Del,                            /* tp_free */
1179 };
1180 
1181 
1182 static PyObject *
_fetch_external_struct_or_union(const struct _cffi_struct_union_s * s,PyObject * included_ffis,int recursion)1183 _fetch_external_struct_or_union(const struct _cffi_struct_union_s *s,
1184                                 PyObject *included_ffis, int recursion)
1185 {
1186     Py_ssize_t i;
1187 
1188     if (included_ffis == NULL)
1189         return NULL;
1190 
1191     if (recursion > 100) {
1192         PyErr_SetString(PyExc_RuntimeError,
1193                         "recursion overflow in ffi.include() delegations");
1194         return NULL;
1195     }
1196 
1197     for (i = 0; i < PyTuple_GET_SIZE(included_ffis); i++) {
1198         FFIObject *ffi1;
1199         const struct _cffi_struct_union_s *s1;
1200         int sindex;
1201         PyObject *x;
1202 
1203         ffi1 = (FFIObject *)PyTuple_GET_ITEM(included_ffis, i);
1204         sindex = search_in_struct_unions(&ffi1->types_builder.ctx, s->name,
1205                                          strlen(s->name));
1206         if (sindex < 0)  /* not found at all */
1207             continue;
1208         s1 = &ffi1->types_builder.ctx.struct_unions[sindex];
1209         if ((s1->flags & (_CFFI_F_EXTERNAL | _CFFI_F_UNION))
1210                 == (s->flags & _CFFI_F_UNION)) {
1211             /* s1 is not external, and the same kind (struct or union) as s */
1212             return _realize_c_struct_or_union(&ffi1->types_builder, sindex);
1213         }
1214         /* not found, look more recursively */
1215         x = _fetch_external_struct_or_union(
1216                 s, ffi1->types_builder.included_ffis, recursion + 1);
1217         if (x != NULL || PyErr_Occurred())
1218             return x;   /* either found, or got an error */
1219     }
1220     return NULL;   /* not found at all, leave without an error */
1221 }
1222