static PyObject *_ffi_new(FFIObject *self, PyObject *args, PyObject *kwds, const cffi_allocator_t *allocator) { CTypeDescrObject *ct; PyObject *arg, *init = Py_None; static char *keywords[] = {"cdecl", "init", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:new", keywords, &arg, &init)) return NULL; ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE); if (ct == NULL) return NULL; return direct_newp(ct, init, allocator); }
static PyObject *ffi_sizeof(FFIObject *self, PyObject *arg) { Py_ssize_t size; CTypeDescrObject *ct = _ffi_type(self, arg, ACCEPT_ALL); if (ct == NULL) return NULL; size = ct->ct_size; if (CData_Check(arg)) { CDataObject *cd = (CDataObject *)arg; if (cd->c_type->ct_flags & CT_ARRAY) size = get_array_length(cd) * cd->c_type->ct_itemdescr->ct_size; } if (size < 0) { PyErr_Format(FFIError, "don't know the size of ctype '%s'", ct->ct_name); return NULL; } return PyInt_FromSsize_t(size); }
static CTypeDescrObject *_ffi_type(FFIObject *ffi, PyObject *arg, int accept) { /* Returns the CTypeDescrObject from the user-supplied 'arg'. Does not return a new reference! */ if ((accept & ACCEPT_STRING) && PyText_Check(arg)) { PyObject *types_dict = ffi->types_builder.types_dict; PyObject *x = PyDict_GetItem(types_dict, arg); if (x == NULL) { char *input_text = PyText_AS_UTF8(arg); int err, index = parse_c_type(&ffi->info, input_text); if (index < 0) return _ffi_bad_type(ffi, input_text); x = realize_c_type_or_func(&ffi->types_builder, ffi->info.output, index); if (x == NULL) return NULL; /* Cache under the name given by 'arg', in addition to the fact that the same ct is probably already cached under its standardized name. In a few cases, it is not, e.g. if it is a primitive; for the purpose of this function, the important point is the following line, which makes sure that in any case the next _ffi_type() with the same 'arg' will succeed early, in PyDict_GetItem() above. */ err = PyDict_SetItem(types_dict, arg, x); Py_DECREF(x); /* we know it was written in types_dict (unless out of mem), so there is at least that ref left */ if (err < 0) return NULL; } if (CTypeDescr_Check(x)) return (CTypeDescrObject *)x; else if (accept & CONSIDER_FN_AS_FNPTR) return unwrap_fn_as_fnptr(x); else return unexpected_fn_type(x); } else if ((accept & ACCEPT_CTYPE) && CTypeDescr_Check(arg)) { return (CTypeDescrObject *)arg; } else if ((accept & ACCEPT_CDATA) && CData_Check(arg)) { return ((CDataObject *)arg)->c_type; } #if PY_MAJOR_VERSION < 3 else if (PyUnicode_Check(arg)) { CTypeDescrObject *result; arg = PyUnicode_AsASCIIString(arg); if (arg == NULL) return NULL; result = _ffi_type(ffi, arg, accept); Py_DECREF(arg); return result; } #endif else { const char *m1 = (accept & ACCEPT_STRING) ? "string" : ""; const char *m2 = (accept & ACCEPT_CTYPE) ? "ctype object" : ""; const char *m3 = (accept & ACCEPT_CDATA) ? "cdata object" : ""; const char *s12 = (*m1 && (*m2 || *m3)) ? " or " : ""; const char *s23 = (*m2 && *m3) ? " or " : ""; PyErr_Format(PyExc_TypeError, "expected a %s%s%s%s%s, got '%.200s'", m1, s12, m2, s23, m3, Py_TYPE(arg)->tp_name); return NULL; } }