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_DECREF(res);
1074 res = NULL;
1075 }
1076 Py_XDECREF(tup);
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 "_cffi_backend.FFI",
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