Empty external/python/cffi am: de77edbe02

Original change: https://android-review.googlesource.com/c/platform/external/python/cffi/+/2984152

Change-Id: Iac23460dbd403e2c877c2706a29e394d2ddc9361
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/AUTHORS b/AUTHORS
deleted file mode 100644
index 370a25d..0000000
--- a/AUTHORS
+++ /dev/null
@@ -1,8 +0,0 @@
-This package has been mostly done by Armin Rigo with help from
-Maciej Fijałkowski. The idea is heavily based (although not directly
-copied) from LuaJIT ffi by Mike Pall.
-
-
-Other contributors:
-
-  Google Inc.
diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index 13f23dd..0000000
--- a/Android.bp
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
-    default_applicable_licenses: ["external_python_cffi_license"],
-}
-
-// Added automatically by a large-scale-change
-// See: http://go/android-license-faq
-license {
-    name: "external_python_cffi_license",
-    visibility: [":__subpackages__"],
-    license_kinds: [
-        "SPDX-license-identifier-MIT",
-    ],
-    license_text: [
-        "LICENSE",
-    ],
-}
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 29225ee..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-
-Except when otherwise stated (look for LICENSE files in directories or
-information at the beginning of each file) all software and
-documentation is licensed as follows: 
-
-    The MIT License
-
-    Permission is hereby granted, free of charge, to any person 
-    obtaining a copy of this software and associated documentation 
-    files (the "Software"), to deal in the Software without 
-    restriction, including without limitation the rights to use, 
-    copy, modify, merge, publish, distribute, sublicense, and/or 
-    sell copies of the Software, and to permit persons to whom the 
-    Software is furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be included 
-    in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
-    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
-    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
-    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
-    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
-    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
-    DEALINGS IN THE SOFTWARE.
-
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index b8ca2e0..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,6 +0,0 @@
-recursive-include cffi *.py *.h
-recursive-include c *.c *.h *.asm *.py win64.obj ffi.lib
-recursive-include testing *.py *.c *.h
-recursive-include doc *.py *.rst Makefile *.bat
-recursive-include demo py.cleanup *.py embedding_test.c manual.c
-include AUTHORS LICENSE setup.py setup_base.py
diff --git a/METADATA b/METADATA
deleted file mode 100644
index db9d268..0000000
--- a/METADATA
+++ /dev/null
@@ -1,17 +0,0 @@
-name: "cffi"
-description:
-    "Foreign Function Interface for Python calling C code."
-
-third_party {
-  url {
-    type: HOMEPAGE
-    value: "https://bitbucket.org/cffi/cffi"
-  }
-  url {
-    type: HG
-    value: "https://bitbucket.org/cffi/cffi/src"
-  }
-  version: "1.15.0"
-  last_upgrade_date { year: 2020 month: 11 day: 8 }
-  license_type: NOTICE
-}
diff --git a/MODULE_LICENSE_MIT b/MODULE_LICENSE_MIT
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_MIT
+++ /dev/null
diff --git a/README.md b/README.md
deleted file mode 100644
index a68639e..0000000
--- a/README.md
+++ /dev/null
@@ -1,30 +0,0 @@
-CFFI
-====
-
-Foreign Function Interface for Python calling C code.
-Please see the [Documentation](http://cffi.readthedocs.org/) or uncompiled
-in the doc/ subdirectory.
-
-Download
---------
-
-[Download page](https://foss.heptapod.net/pypy/cffi/-/tags)
-
-Contact
--------
-
-[Mailing list](https://groups.google.com/forum/#!forum/python-cffi)
-
-Testing/development tips
-------------------------
-
-To run tests under CPython, run::
-
-    pip install pytest     # if you don't have py.test already
-    pip install pycparser
-    python setup.py build_ext -f -i
-    py.test c/ testing/
-
-If you run in another directory (either the tests or another program),
-you should use the environment variable ``PYTHONPATH=/path`` to point
-to the location that contains the ``_cffi_backend.so`` just compiled.
diff --git a/c/.libs_cffi_backend/libffi-9c61262e.so.8.1.0 b/c/.libs_cffi_backend/libffi-9c61262e.so.8.1.0
deleted file mode 100755
index 82b4232..0000000
--- a/c/.libs_cffi_backend/libffi-9c61262e.so.8.1.0
+++ /dev/null
Binary files differ
diff --git a/c/Android.bp b/c/Android.bp
deleted file mode 100644
index 96565df..0000000
--- a/c/Android.bp
+++ /dev/null
@@ -1,44 +0,0 @@
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "external_python_cffi_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-MIT
-    default_applicable_licenses: ["external_python_cffi_license"],
-}
-
-python_library {
-    name: "py-cffi-backend",
-    host_supported: true,
-    srcs: [
-        "_dummy_file_cffi_backend.py",
-    ],
-    data: [
-        ":py-cffi-backend-files"
-    ],
-}
-
-filegroup {
-    name: "py-cffi-backend-files",
-    srcs: [
-        "_cffi_backend.so",
-    ],
-}
-
-python_library {
-    name: "py-cffi-backend-libffi",
-    host_supported: true,
-    srcs: [
-        "_dummy_file_libffi.py",
-    ],
-    data: [
-        ":py-cffi-backend-libffi-files"
-    ],
-}
-
-filegroup {
-    name: "py-cffi-backend-libffi-files",
-    srcs: [
-        ".libs_cffi_backend/libffi-9c61262e.so.8.1.0",
-    ],
-}
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
deleted file mode 100644
index ffecbf9..0000000
--- a/c/_cffi_backend.c
+++ /dev/null
@@ -1,8083 +0,0 @@
-#define PY_SSIZE_T_CLEAN
-#include <Python.h>
-#include "structmember.h"
-
-#define CFFI_VERSION  "1.15.0"
-
-#ifdef MS_WIN32
-#include <windows.h>
-#include "misc_win32.h"
-#else
-#include <stddef.h>
-#include <stdint.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include <ffi.h>
-#include <sys/mman.h>
-#endif
-
-/* this block of #ifs should be kept exactly identical between
-   c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py */
-#if defined(_MSC_VER)
-# include <malloc.h>   /* for alloca() */
-# if _MSC_VER < 1600   /* MSVC < 2010 */
-   typedef __int8 int8_t;
-   typedef __int16 int16_t;
-   typedef __int32 int32_t;
-   typedef __int64 int64_t;
-   typedef unsigned __int8 uint8_t;
-   typedef unsigned __int16 uint16_t;
-   typedef unsigned __int32 uint32_t;
-   typedef unsigned __int64 uint64_t;
-   typedef __int8 int_least8_t;
-   typedef __int16 int_least16_t;
-   typedef __int32 int_least32_t;
-   typedef __int64 int_least64_t;
-   typedef unsigned __int8 uint_least8_t;
-   typedef unsigned __int16 uint_least16_t;
-   typedef unsigned __int32 uint_least32_t;
-   typedef unsigned __int64 uint_least64_t;
-   typedef __int8 int_fast8_t;
-   typedef __int16 int_fast16_t;
-   typedef __int32 int_fast32_t;
-   typedef __int64 int_fast64_t;
-   typedef unsigned __int8 uint_fast8_t;
-   typedef unsigned __int16 uint_fast16_t;
-   typedef unsigned __int32 uint_fast32_t;
-   typedef unsigned __int64 uint_fast64_t;
-   typedef __int64 intmax_t;
-   typedef unsigned __int64 uintmax_t;
-# else
-#  include <stdint.h>
-# endif
-# if _MSC_VER < 1800   /* MSVC < 2013 */
-   typedef unsigned char _Bool;
-# endif
-#else
-# include <stdint.h>
-# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux)
-#  include <alloca.h>
-# endif
-#endif
-
-
-/* Define the following macro ONLY if you trust libffi's version of
- * ffi_closure_alloc() more than the code in malloc_closure.h.
- * IMPORTANT: DO NOT ENABLE THIS ON LINUX, unless you understand exactly
- * why I recommend against it and decide that you trust it more than my
- * analysis below.
- *
- * There are two versions of this code: one inside libffi itself, and
- * one inside malloc_closure.h here.  Both should be fine as long as the
- * Linux distribution does _not_ enable extra security features.  If it
- * does, then the code in malloc_closure.h will cleanly crash because
- * there is no reasonable way to obtain a read-write-execute memory
- * page.  On the other hand, the code in libffi will appear to
- * work---but will actually randomly crash after a fork() if the child
- * does not immediately call exec().  This second crash is of the kind
- * that can be turned into an attack vector by a motivated attacker.
- * So, _enabling_ extra security features _opens_ an attack vector.
- * That sounds like a horribly bad idea to me, and is the reason for why
- * I prefer CFFI crashing cleanly.
- *
- * Currently, we use libffi's ffi_closure_alloc() on NetBSD.  It is
- * known that on the NetBSD kernel, a different strategy is used which
- * should not be open to the fork() bug.
- *
- * This is also used on macOS, provided we are executing on macOS 10.15 or
- * above.  It's a mess because it needs runtime checks in that case.
- */
-#ifdef __NetBSD__
-
-# define CFFI_CHECK_FFI_CLOSURE_ALLOC 1
-# define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 1
-# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC 1
-# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 1
-# define CFFI_CHECK_FFI_PREP_CIF_VAR 0
-# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 0
-
-#elif defined(__APPLE__) && defined(FFI_AVAILABLE_APPLE)
-
-# define CFFI_CHECK_FFI_CLOSURE_ALLOC __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
-# define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 1
-# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
-# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 1
-# define CFFI_CHECK_FFI_PREP_CIF_VAR __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
-# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 1
-
-#else
-
-# define CFFI_CHECK_FFI_CLOSURE_ALLOC 0
-# define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 0
-# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC 0
-# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 0
-# define CFFI_CHECK_FFI_PREP_CIF_VAR 0
-# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 0
-
-#endif
-
-/* always includes this, even if it turns out not to be used on NetBSD
-   because calls are behind "if (0)" */
-#include "malloc_closure.h"
-
-
-#if PY_MAJOR_VERSION >= 3
-# define STR_OR_BYTES "bytes"
-# define PyText_Type PyUnicode_Type
-# define PyText_Check PyUnicode_Check
-# define PyTextAny_Check PyUnicode_Check
-# define PyText_FromFormat PyUnicode_FromFormat
-# define PyText_AsUTF8 _PyUnicode_AsString   /* PyUnicode_AsUTF8 in Py3.3 */
-# define PyText_AS_UTF8 _PyUnicode_AsString
-# if PY_VERSION_HEX >= 0x03030000
-#  define PyText_GetSize PyUnicode_GetLength
-# else
-#  define PyText_GetSize PyUnicode_GetSize
-# endif
-# define PyText_FromString PyUnicode_FromString
-# define PyText_FromStringAndSize PyUnicode_FromStringAndSize
-# define PyText_InternInPlace PyUnicode_InternInPlace
-# define PyText_InternFromString PyUnicode_InternFromString
-# define PyIntOrLong_Check PyLong_Check
-#else
-# define STR_OR_BYTES "str"
-# define PyText_Type PyString_Type
-# define PyText_Check PyString_Check
-# define PyTextAny_Check(op) (PyString_Check(op) || PyUnicode_Check(op))
-# define PyText_FromFormat PyString_FromFormat
-# define PyText_AsUTF8 PyString_AsString
-# define PyText_AS_UTF8 PyString_AS_STRING
-# define PyText_GetSize PyString_Size
-# define PyText_FromString PyString_FromString
-# define PyText_FromStringAndSize PyString_FromStringAndSize
-# define PyText_InternInPlace PyString_InternInPlace
-# define PyText_InternFromString PyString_InternFromString
-# define PyIntOrLong_Check(op) (PyInt_Check(op) || PyLong_Check(op))
-#endif
-
-#if PY_MAJOR_VERSION >= 3
-# define PyInt_FromLong PyLong_FromLong
-# define PyInt_FromSsize_t PyLong_FromSsize_t
-# define PyInt_AsSsize_t PyLong_AsSsize_t
-# define PyInt_AsLong PyLong_AsLong
-#endif
-
-#if PY_MAJOR_VERSION >= 3
-/* This is the default on Python3 and constant has been removed. */
-# define Py_TPFLAGS_CHECKTYPES 0
-#endif
-
-#if PY_MAJOR_VERSION < 3
-# undef PyCapsule_GetPointer
-# undef PyCapsule_New
-# define PyCapsule_GetPointer(capsule, name) \
-    (PyCObject_AsVoidPtr(capsule))
-# define PyCapsule_New(pointer, name, destructor) \
-    (PyCObject_FromVoidPtr(pointer, destructor))
-#endif
-
-#if PY_VERSION_HEX < 0x030900a4
-# define Py_SET_REFCNT(obj, val) (Py_REFCNT(obj) = (val))
-#endif
-
-#if PY_VERSION_HEX >= 0x03080000
-# define USE_WRITEUNRAISABLEMSG
-#endif
-
-/************************************************************/
-
-/* base type flag: exactly one of the following: */
-#define CT_PRIMITIVE_SIGNED   0x001   /* signed integer */
-#define CT_PRIMITIVE_UNSIGNED 0x002   /* unsigned integer */
-#define CT_PRIMITIVE_CHAR     0x004   /* char, wchar_t, charN_t */
-#define CT_PRIMITIVE_FLOAT    0x008   /* float, double, long double */
-#define CT_POINTER            0x010   /* pointer, excluding ptr-to-func */
-#define CT_ARRAY              0x020   /* array */
-#define CT_STRUCT             0x040   /* struct */
-#define CT_UNION              0x080   /* union */
-#define CT_FUNCTIONPTR        0x100   /* pointer to function */
-#define CT_VOID               0x200   /* void */
-#define CT_PRIMITIVE_COMPLEX  0x400   /* float _Complex, double _Complex */
-
-/* other flags that may also be set in addition to the base flag: */
-#define CT_IS_VOIDCHAR_PTR     0x00001000
-#define CT_PRIMITIVE_FITS_LONG 0x00002000
-#define CT_IS_OPAQUE           0x00004000
-#define CT_IS_ENUM             0x00008000
-#define CT_IS_PTR_TO_OWNED     0x00010000 /* only owned if CDataOwning_Type */
-#define CT_CUSTOM_FIELD_POS    0x00020000
-#define CT_IS_LONGDOUBLE       0x00040000
-#define CT_IS_BOOL             0x00080000
-#define CT_IS_FILE             0x00100000
-#define CT_IS_VOID_PTR         0x00200000
-#define CT_WITH_VAR_ARRAY      0x00400000 /* with open-ended array, anywhere */
-/* unused                      0x00800000 */
-#define CT_LAZY_FIELD_LIST     0x01000000
-#define CT_WITH_PACKED_CHANGE  0x02000000
-#define CT_IS_SIGNED_WCHAR     0x04000000
-#define CT_PRIMITIVE_ANY  (CT_PRIMITIVE_SIGNED |        \
-                           CT_PRIMITIVE_UNSIGNED |      \
-                           CT_PRIMITIVE_CHAR |          \
-                           CT_PRIMITIVE_FLOAT |         \
-                           CT_PRIMITIVE_COMPLEX)
-
-typedef struct _ctypedescr {
-    PyObject_VAR_HEAD
-
-    struct _ctypedescr *ct_itemdescr;  /* ptrs and arrays: the item type */
-    PyObject *ct_stuff;                /* structs: dict of the fields
-                                          arrays: ctypedescr of the ptr type
-                                          function: tuple(abi, ctres, ctargs..)
-                                          enum: pair {"name":x},{x:"name"}
-                                          ptrs: lazily, ctypedescr of array */
-    void *ct_extra;                    /* structs: first field (not a ref!)
-                                          function types: cif_description
-                                          primitives: prebuilt "cif" object */
-
-    PyObject *ct_weakreflist;    /* weakref support */
-
-    PyObject *ct_unique_key;    /* key in unique_cache (a string, but not
-                                   human-readable) */
-
-    Py_ssize_t ct_size;     /* size of instances, or -1 if unknown */
-    Py_ssize_t ct_length;   /* length of arrays, or -1 if unknown;
-                               or alignment of primitive and struct types;
-                               always -1 for pointers */
-    int ct_flags;           /* CT_xxx flags */
-
-    int ct_name_position;   /* index in ct_name of where to put a var name */
-    char ct_name[1];        /* string, e.g. "int *" for pointers to ints */
-} CTypeDescrObject;
-
-typedef struct {
-    PyObject_HEAD
-    CTypeDescrObject *c_type;
-    char *c_data;
-    PyObject *c_weakreflist;
-} CDataObject;
-
-typedef struct cfieldobject_s {
-    PyObject_HEAD
-    CTypeDescrObject *cf_type;
-    Py_ssize_t cf_offset;
-    short cf_bitshift;   /* >= 0: bitshift; or BS_REGULAR or BS_EMPTY_ARRAY */
-    short cf_bitsize;
-    unsigned char cf_flags;   /* BF_... */
-    struct cfieldobject_s *cf_next;
-} CFieldObject;
-#define BS_REGULAR            (-1) /* a regular field, not with bitshift */
-#define BS_EMPTY_ARRAY        (-2) /* a field declared 'type[0]' or 'type[]' */
-#define BF_IGNORE_IN_CTOR     0x01 /* union field not in the first place */
-
-static PyTypeObject CTypeDescr_Type;
-static PyTypeObject CField_Type;
-static PyTypeObject CData_Type;
-static PyTypeObject CDataOwning_Type;
-static PyTypeObject CDataOwningGC_Type;
-static PyTypeObject CDataFromBuf_Type;
-static PyTypeObject CDataGCP_Type;
-
-#define CTypeDescr_Check(ob)  (Py_TYPE(ob) == &CTypeDescr_Type)
-#define CData_Check(ob)       (Py_TYPE(ob) == &CData_Type ||            \
-                               Py_TYPE(ob) == &CDataOwning_Type ||      \
-                               Py_TYPE(ob) == &CDataOwningGC_Type ||    \
-                               Py_TYPE(ob) == &CDataFromBuf_Type ||     \
-                               Py_TYPE(ob) == &CDataGCP_Type)
-#define CDataOwn_Check(ob)    (Py_TYPE(ob) == &CDataOwning_Type ||      \
-                               Py_TYPE(ob) == &CDataOwningGC_Type)
-
-typedef union {
-    unsigned char m_char;
-    unsigned short m_short;
-    unsigned int m_int;
-    unsigned long m_long;
-    unsigned long long m_longlong;
-    float m_float;
-    double m_double;
-    long double m_longdouble;
-} union_alignment;
-
-typedef struct {
-    CDataObject head;
-    union_alignment alignment;
-} CDataObject_casted_primitive;
-
-typedef struct {
-    CDataObject head;
-    union_alignment alignment;
-} CDataObject_own_nolength;
-
-typedef struct {
-    CDataObject head;
-    Py_ssize_t length;
-    union_alignment alignment;
-} CDataObject_own_length;
-
-typedef struct {
-    CDataObject head;
-    PyObject *structobj;   /* for ffi.new_handle() or ffi.new("struct *") */
-} CDataObject_own_structptr;
-
-typedef struct {
-    CDataObject head;
-    Py_ssize_t length;     /* same as CDataObject_own_length up to here */
-    Py_buffer *bufferview;
-} CDataObject_frombuf;
-
-typedef struct {
-    CDataObject head;
-    Py_ssize_t length;     /* same as CDataObject_own_length up to here */
-    PyObject *origobj;
-    PyObject *destructor;
-} CDataObject_gcp;
-
-typedef struct {
-    CDataObject head;
-    ffi_closure *closure;
-} CDataObject_closure;
-
-typedef struct {
-    ffi_cif cif;
-    /* the following information is used when doing the call:
-       - a buffer of size 'exchange_size' is malloced
-       - the arguments are converted from Python objects to raw data
-       - the i'th raw data is stored at 'buffer + exchange_offset_arg[1+i]'
-       - the call is done
-       - the result is read back from 'buffer + exchange_offset_arg[0]' */
-    Py_ssize_t exchange_size;
-    Py_ssize_t exchange_offset_arg[1];
-} cif_description_t;
-
-#define ADD_WRAPAROUND(x, y)  ((Py_ssize_t)(((size_t)(x)) + ((size_t)(y))))
-#define MUL_WRAPAROUND(x, y)  ((Py_ssize_t)(((size_t)(x)) * ((size_t)(y))))
-
-
-/* whenever running Python code, the errno is saved in this thread-local
-   variable */
-#ifndef MS_WIN32
-# include "misc_thread_posix.h"
-#endif
-
-#include "minibuffer.h"
-
-#if PY_MAJOR_VERSION >= 3
-# include "file_emulator.h"
-#endif
-
-#ifdef PyUnicode_KIND     /* Python >= 3.3 */
-# include "wchar_helper_3.h"
-#else
-# include "wchar_helper.h"
-#endif
-
-#include "../cffi/_cffi_errors.h"
-
-typedef struct _cffi_allocator_s {
-    PyObject *ca_alloc, *ca_free;
-    int ca_dont_clear;
-} cffi_allocator_t;
-static const cffi_allocator_t default_allocator = { NULL, NULL, 0 };
-static PyObject *FFIError;
-static PyObject *unique_cache;
-
-/************************************************************/
-
-static CTypeDescrObject *
-ctypedescr_new(int name_size)
-{
-    CTypeDescrObject *ct = PyObject_GC_NewVar(CTypeDescrObject,
-                                              &CTypeDescr_Type,
-                                              name_size);
-    if (ct == NULL)
-        return NULL;
-
-    ct->ct_itemdescr = NULL;
-    ct->ct_stuff = NULL;
-    ct->ct_weakreflist = NULL;
-    ct->ct_unique_key = NULL;
-    PyObject_GC_Track(ct);
-    return ct;
-}
-
-static CTypeDescrObject *
-ctypedescr_new_on_top(CTypeDescrObject *ct_base, const char *extra_text,
-                      int extra_position)
-{
-    int base_name_len = strlen(ct_base->ct_name);
-    int extra_name_len = strlen(extra_text);
-    CTypeDescrObject *ct = ctypedescr_new(base_name_len + extra_name_len + 1);
-    char *p;
-    if (ct == NULL)
-        return NULL;
-
-    Py_INCREF(ct_base);
-    ct->ct_itemdescr = ct_base;
-    ct->ct_name_position = ct_base->ct_name_position + extra_position;
-
-    p = ct->ct_name;
-    memcpy(p, ct_base->ct_name, ct_base->ct_name_position);
-    p += ct_base->ct_name_position;
-    memcpy(p, extra_text, extra_name_len);
-    p += extra_name_len;
-    memcpy(p, ct_base->ct_name + ct_base->ct_name_position,
-           base_name_len - ct_base->ct_name_position + 1);
-
-    return ct;
-}
-
-static PyObject *
-ctypedescr_repr(CTypeDescrObject *ct)
-{
-    return PyText_FromFormat("<ctype '%s'>", ct->ct_name);
-}
-
-static void
-ctypedescr_dealloc(CTypeDescrObject *ct)
-{
-    PyObject_GC_UnTrack(ct);
-    if (ct->ct_weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) ct);
-
-    if (ct->ct_unique_key != NULL) {
-        /* revive dead object temporarily for DelItem */
-        Py_SET_REFCNT(ct, 43);
-        PyDict_DelItem(unique_cache, ct->ct_unique_key);
-        assert(Py_REFCNT(ct) == 42);
-        Py_SET_REFCNT(ct, 0);
-        Py_DECREF(ct->ct_unique_key);
-    }
-    Py_XDECREF(ct->ct_itemdescr);
-    Py_XDECREF(ct->ct_stuff);
-    if (ct->ct_flags & CT_FUNCTIONPTR)
-        PyObject_Free(ct->ct_extra);
-    Py_TYPE(ct)->tp_free((PyObject *)ct);
-}
-
-static int
-ctypedescr_traverse(CTypeDescrObject *ct, visitproc visit, void *arg)
-{
-    Py_VISIT(ct->ct_itemdescr);
-    Py_VISIT(ct->ct_stuff);
-    return 0;
-}
-
-static int
-ctypedescr_clear(CTypeDescrObject *ct)
-{
-    Py_CLEAR(ct->ct_itemdescr);
-    Py_CLEAR(ct->ct_stuff);
-    return 0;
-}
-
-
-static PyObject *nosuchattr(const char *attr)
-{
-    PyErr_SetString(PyExc_AttributeError, attr);
-    return NULL;
-}
-
-static PyObject *ctypeget_kind(CTypeDescrObject *ct, void *context)
-{
-    char *result;
-    if (ct->ct_flags & CT_PRIMITIVE_ANY) {
-        if (ct->ct_flags & CT_IS_ENUM)
-            result = "enum";
-        else
-            result = "primitive";
-    }
-    else if (ct->ct_flags & CT_POINTER) {
-        result = "pointer";
-    }
-    else if (ct->ct_flags & CT_ARRAY) {
-        result = "array";
-    }
-    else if (ct->ct_flags & CT_VOID) {
-        result = "void";
-    }
-    else if (ct->ct_flags & CT_STRUCT) {
-        result = "struct";
-    }
-    else if (ct->ct_flags & CT_UNION) {
-        result = "union";
-    }
-    else if (ct->ct_flags & CT_FUNCTIONPTR) {
-        result = "function";
-    }
-    else
-        result = "?";
-
-    return PyText_FromString(result);
-}
-
-static PyObject *ctypeget_cname(CTypeDescrObject *ct, void *context)
-{
-    return PyText_FromString(ct->ct_name);
-}
-
-static PyObject *ctypeget_item(CTypeDescrObject *ct, void *context)
-{
-    if (ct->ct_flags & (CT_POINTER | CT_ARRAY)) {
-        Py_INCREF(ct->ct_itemdescr);
-        return (PyObject *)ct->ct_itemdescr;
-    }
-    return nosuchattr("item");
-}
-
-static PyObject *ctypeget_length(CTypeDescrObject *ct, void *context)
-{
-    if (ct->ct_flags & CT_ARRAY) {
-        if (ct->ct_length >= 0) {
-            return PyInt_FromSsize_t(ct->ct_length);
-        }
-        else {
-            Py_INCREF(Py_None);
-            return Py_None;
-        }
-    }
-    return nosuchattr("length");
-}
-
-static PyObject *
-get_field_name(CTypeDescrObject *ct, CFieldObject *cf);   /* forward */
-
-/* returns 0 if the struct ctype is opaque, 1 if it is not, or -1 if
-   an exception occurs */
-#define force_lazy_struct(ct)                                           \
-    ((ct)->ct_stuff != NULL ? 1 : do_realize_lazy_struct(ct))
-
-static int do_realize_lazy_struct(CTypeDescrObject *ct);
-/* forward, implemented in realize_c_type.c */
-
-static PyObject *ctypeget_fields(CTypeDescrObject *ct, void *context)
-{
-    if (ct->ct_flags & (CT_STRUCT | CT_UNION)) {
-        if (!(ct->ct_flags & CT_IS_OPAQUE)) {
-            CFieldObject *cf;
-            PyObject *res;
-            if (force_lazy_struct(ct) < 0)
-                return NULL;
-            res = PyList_New(0);
-            if (res == NULL)
-                return NULL;
-            for (cf = (CFieldObject *)ct->ct_extra;
-                 cf != NULL; cf = cf->cf_next) {
-                PyObject *o = PyTuple_Pack(2, get_field_name(ct, cf),
-                                           (PyObject *)cf);
-                int err = (o != NULL) ? PyList_Append(res, o) : -1;
-                Py_XDECREF(o);
-                if (err < 0) {
-                    Py_DECREF(res);
-                    return NULL;
-                }
-            }
-            return res;
-        }
-        else {
-            Py_INCREF(Py_None);
-            return Py_None;
-        }
-    }
-    return nosuchattr("fields");
-}
-
-static PyObject *ctypeget_args(CTypeDescrObject *ct, void *context)
-{
-    if (ct->ct_flags & CT_FUNCTIONPTR) {
-        PyObject *t = ct->ct_stuff;
-        return PyTuple_GetSlice(t, 2, PyTuple_GET_SIZE(t));
-    }
-    return nosuchattr("args");
-}
-
-static PyObject *ctypeget_result(CTypeDescrObject *ct, void *context)
-{
-    if (ct->ct_flags & CT_FUNCTIONPTR) {
-        PyObject *res = PyTuple_GetItem(ct->ct_stuff, 1);
-        Py_XINCREF(res);
-        return res;
-    }
-    return nosuchattr("result");
-}
-
-static PyObject *ctypeget_ellipsis(CTypeDescrObject *ct, void *context)
-{
-    if (ct->ct_flags & CT_FUNCTIONPTR) {
-        PyObject *res = ct->ct_extra ? Py_False : Py_True;
-        Py_INCREF(res);
-        return res;
-    }
-    return nosuchattr("ellipsis");
-}
-
-static PyObject *ctypeget_abi(CTypeDescrObject *ct, void *context)
-{
-    if (ct->ct_flags & CT_FUNCTIONPTR) {
-        PyObject *res = PyTuple_GetItem(ct->ct_stuff, 0);
-        Py_XINCREF(res);
-        return res;
-    }
-    return nosuchattr("abi");
-}
-
-static PyObject *ctypeget_elements(CTypeDescrObject *ct, void *context)
-{
-    if (ct->ct_flags & CT_IS_ENUM) {
-        PyObject *res = PyTuple_GetItem(ct->ct_stuff, 1);
-        if (res) res = PyDict_Copy(res);
-        return res;
-    }
-    return nosuchattr("elements");
-}
-
-static PyObject *ctypeget_relements(CTypeDescrObject *ct, void *context)
-{
-    if (ct->ct_flags & CT_IS_ENUM) {
-        PyObject *res = PyTuple_GetItem(ct->ct_stuff, 0);
-        if (res) res = PyDict_Copy(res);
-        return res;
-    }
-    return nosuchattr("relements");
-}
-
-static PyGetSetDef ctypedescr_getsets[] = {
-    {"kind", (getter)ctypeget_kind, NULL, "kind"},
-    {"cname", (getter)ctypeget_cname, NULL, "C name"},
-    {"item", (getter)ctypeget_item, NULL, "pointer to, or array of"},
-    {"length", (getter)ctypeget_length, NULL, "array length or None"},
-    {"fields", (getter)ctypeget_fields, NULL, "struct or union fields"},
-    {"args", (getter)ctypeget_args, NULL, "function argument types"},
-    {"result", (getter)ctypeget_result, NULL, "function result type"},
-    {"ellipsis", (getter)ctypeget_ellipsis, NULL, "function has '...'"},
-    {"abi", (getter)ctypeget_abi, NULL, "function ABI"},
-    {"elements", (getter)ctypeget_elements, NULL, "enum elements"},
-    {"relements", (getter)ctypeget_relements, NULL, "enum elements, reverse"},
-    {NULL}                        /* sentinel */
-};
-
-static PyObject *
-ctypedescr_dir(PyObject *ct, PyObject *noarg)
-{
-    int err;
-    struct PyGetSetDef *gsdef;
-    PyObject *res = PyList_New(0);
-    if (res == NULL)
-        return NULL;
-
-    for (gsdef = ctypedescr_getsets; gsdef->name; gsdef++) {
-        PyObject *x = PyObject_GetAttrString(ct, gsdef->name);
-        if (x == NULL) {
-            PyErr_Clear();
-        }
-        else {
-            Py_DECREF(x);
-            x = PyText_FromString(gsdef->name);
-            err = (x != NULL) ? PyList_Append(res, x) : -1;
-            Py_XDECREF(x);
-            if (err < 0) {
-                Py_DECREF(res);
-                return NULL;
-            }
-        }
-    }
-    return res;
-}
-
-static PyMethodDef ctypedescr_methods[] = {
-    {"__dir__",   ctypedescr_dir,  METH_NOARGS},
-    {NULL,        NULL}           /* sentinel */
-};
-
-static PyTypeObject CTypeDescr_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.CType",
-    offsetof(CTypeDescrObject, ct_name),
-    sizeof(char),
-    (destructor)ctypedescr_dealloc,             /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_compare */
-    (reprfunc)ctypedescr_repr,                  /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    PyObject_GenericGetAttr,                    /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
-    0,                                          /* tp_doc */
-    (traverseproc)ctypedescr_traverse,          /* tp_traverse */
-    (inquiry)ctypedescr_clear,                  /* tp_clear */
-    0,                                          /* tp_richcompare */
-    offsetof(CTypeDescrObject, ct_weakreflist), /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    ctypedescr_methods,                         /* tp_methods */
-    0,                                          /* tp_members */
-    ctypedescr_getsets,                         /* tp_getset */
-};
-
-/************************************************************/
-
-static PyObject *
-get_field_name(CTypeDescrObject *ct, CFieldObject *cf)
-{
-    Py_ssize_t i = 0;
-    PyObject *d_key, *d_value;
-    while (PyDict_Next(ct->ct_stuff, &i, &d_key, &d_value)) {
-        if (d_value == (PyObject *)cf)
-            return d_key;
-    }
-    Py_FatalError("_cffi_backend: get_field_name()");
-    return NULL;
-}
-
-static void
-cfield_dealloc(CFieldObject *cf)
-{
-    Py_DECREF(cf->cf_type);
-    PyObject_Del(cf);
-}
-
-#undef OFF
-#define OFF(x) offsetof(CFieldObject, x)
-
-static PyMemberDef cfield_members[] = {
-    {"type", T_OBJECT, OFF(cf_type), READONLY},
-    {"offset", T_PYSSIZET, OFF(cf_offset), READONLY},
-    {"bitshift", T_SHORT, OFF(cf_bitshift), READONLY},
-    {"bitsize", T_SHORT, OFF(cf_bitsize), READONLY},
-    {"flags", T_UBYTE, OFF(cf_flags), READONLY},
-    {NULL}      /* Sentinel */
-};
-#undef OFF
-
-static PyTypeObject CField_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.CField",
-    sizeof(CFieldObject),
-    0,
-    (destructor)cfield_dealloc,                 /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_compare */
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    PyObject_GenericGetAttr,                    /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                         /* tp_flags */
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,                                          /* tp_methods */
-    cfield_members,                             /* tp_members */
-};
-
-/************************************************************/
-
-static int
-CDataObject_Or_PyFloat_Check(PyObject *ob)
-{
-    return (PyFloat_Check(ob) ||
-            (CData_Check(ob) &&
-             (((CDataObject *)ob)->c_type->ct_flags & CT_PRIMITIVE_FLOAT)));
-}
-
-static PY_LONG_LONG
-_my_PyLong_AsLongLong(PyObject *ob)
-{
-    /* (possibly) convert and cast a Python object to a long long.
-       Like PyLong_AsLongLong(), this version accepts a Python int too, and
-       does convertions from other types of objects.  The difference is that
-       this version refuses floats. */
-#if PY_MAJOR_VERSION < 3
-    if (PyInt_Check(ob)) {
-        return PyInt_AS_LONG(ob);
-    }
-    else 
-#endif
-    if (PyLong_Check(ob)) {
-        return PyLong_AsLongLong(ob);
-    }
-    else {
-        PyObject *io;
-        PY_LONG_LONG res;
-        PyNumberMethods *nb = ob->ob_type->tp_as_number;
-
-        if (CDataObject_Or_PyFloat_Check(ob) ||
-                nb == NULL || nb->nb_int == NULL) {
-            PyErr_SetString(PyExc_TypeError, "an integer is required");
-            return -1;
-        }
-        io = (*nb->nb_int) (ob);
-        if (io == NULL)
-            return -1;
-
-        if (PyIntOrLong_Check(io)) {
-            res = _my_PyLong_AsLongLong(io);
-        }
-        else {
-            PyErr_SetString(PyExc_TypeError, "integer conversion failed");
-            res = -1;
-        }
-        Py_DECREF(io);
-        return res;
-    }
-}
-
-static unsigned PY_LONG_LONG
-_my_PyLong_AsUnsignedLongLong(PyObject *ob, int strict)
-{
-    /* (possibly) convert and cast a Python object to an unsigned long long.
-       Like PyLong_AsLongLong(), this version accepts a Python int too, and
-       does convertions from other types of objects.  If 'strict', complains
-       with OverflowError and refuses floats.  If '!strict', rounds floats
-       and masks the result. */
-#if PY_MAJOR_VERSION < 3
-    if (PyInt_Check(ob)) {
-        long value1 = PyInt_AS_LONG(ob);
-        if (strict && value1 < 0)
-            goto negative;
-        return (unsigned PY_LONG_LONG)(PY_LONG_LONG)value1;
-    }
-    else
-#endif
-    if (PyLong_Check(ob)) {
-        if (strict) {
-            if (_PyLong_Sign(ob) < 0)
-                goto negative;
-            return PyLong_AsUnsignedLongLong(ob);
-        }
-        else {
-            return PyLong_AsUnsignedLongLongMask(ob);
-        }
-    }
-    else {
-        PyObject *io;
-        unsigned PY_LONG_LONG res;
-        PyNumberMethods *nb = ob->ob_type->tp_as_number;
-
-        if ((strict && CDataObject_Or_PyFloat_Check(ob)) ||
-                nb == NULL || nb->nb_int == NULL) {
-            PyErr_SetString(PyExc_TypeError, "an integer is required");
-            return (unsigned PY_LONG_LONG)-1;
-        }
-        io = (*nb->nb_int) (ob);
-        if (io == NULL)
-            return (unsigned PY_LONG_LONG)-1;
-
-        if (PyIntOrLong_Check(io)) {
-            res = _my_PyLong_AsUnsignedLongLong(io, strict);
-        }
-        else {
-            PyErr_SetString(PyExc_TypeError, "integer conversion failed");
-            res = (unsigned PY_LONG_LONG)-1;
-        }
-        Py_DECREF(io);
-        return res;
-    }
-
- negative:
-    PyErr_SetString(PyExc_OverflowError,
-                    "can't convert negative number to unsigned");
-    return (unsigned PY_LONG_LONG)-1;
-}
-
-#define _read_raw_data(type)                    \
-    do {                                        \
-        if (size == sizeof(type)) {             \
-            type r;                             \
-            memcpy(&r, target, sizeof(type));   \
-            return r;                           \
-        }                                       \
-    } while(0)
-
-static PY_LONG_LONG
-read_raw_signed_data(char *target, int size)
-{
-    _read_raw_data(signed char);
-    _read_raw_data(short);
-    _read_raw_data(int);
-    _read_raw_data(long);
-    _read_raw_data(PY_LONG_LONG);
-    Py_FatalError("read_raw_signed_data: bad integer size");
-    return 0;
-}
-
-static unsigned PY_LONG_LONG
-read_raw_unsigned_data(char *target, int size)
-{
-    _read_raw_data(unsigned char);
-    _read_raw_data(unsigned short);
-    _read_raw_data(unsigned int);
-    _read_raw_data(unsigned long);
-    _read_raw_data(unsigned PY_LONG_LONG);
-    Py_FatalError("read_raw_unsigned_data: bad integer size");
-    return 0;
-}
-
-#ifdef __GNUC__
-/* This is a workaround for what I think is a GCC bug on several
-   platforms.  See issue #378. */
-__attribute__((noinline))
-#endif
-void _cffi_memcpy(char *target, const void *src, size_t size)
-{
-    memcpy(target, src, size);
-}
-
-#define _write_raw_data(type)                           \
-    do {                                                \
-        if (size == sizeof(type)) {                     \
-            type r = (type)source;                      \
-            _cffi_memcpy(target, &r, sizeof(type));           \
-            return;                                     \
-        }                                               \
-    } while(0)
-
-static void
-write_raw_integer_data(char *target, unsigned PY_LONG_LONG source, int size)
-{
-    _write_raw_data(unsigned char);
-    _write_raw_data(unsigned short);
-    _write_raw_data(unsigned int);
-    _write_raw_data(unsigned long);
-    _write_raw_data(unsigned PY_LONG_LONG);
-    Py_FatalError("write_raw_integer_data: bad integer size");
-}
-
-static double
-read_raw_float_data(char *target, int size)
-{
-    _read_raw_data(float);
-    _read_raw_data(double);
-    Py_FatalError("read_raw_float_data: bad float size");
-    return 0;
-}
-
-static long double
-read_raw_longdouble_data(char *target)
-{
-    int size = sizeof(long double);
-    _read_raw_data(long double);
-    Py_FatalError("read_raw_longdouble_data: bad long double size");
-    return 0;
-}
-
-static Py_complex
-read_raw_complex_data(char *target, int size)
-{
-    Py_complex r = {0.0, 0.0};
-    if (size == 2*sizeof(float)) {
-        float real_part, imag_part;
-        memcpy(&real_part, target + 0,             sizeof(float));
-        memcpy(&imag_part, target + sizeof(float), sizeof(float));
-        r.real = real_part;
-        r.imag = imag_part;
-        return r;
-    }
-    if (size == 2*sizeof(double)) {
-        memcpy(&r, target, 2*sizeof(double));
-        return r;
-    }
-    Py_FatalError("read_raw_complex_data: bad complex size");
-    return r;
-}
-
-static void
-write_raw_float_data(char *target, double source, int size)
-{
-    _write_raw_data(float);
-    _write_raw_data(double);
-    Py_FatalError("write_raw_float_data: bad float size");
-}
-
-static void
-write_raw_longdouble_data(char *target, long double source)
-{
-    int size = sizeof(long double);
-    _write_raw_data(long double);
-}
-
-#define _write_raw_complex_data(type)                      \
-    do {                                                   \
-        if (size == 2*sizeof(type)) {                      \
-            type r = (type)source.real;                    \
-            type i = (type)source.imag;                    \
-            _cffi_memcpy(target, &r, sizeof(type));              \
-            _cffi_memcpy(target+sizeof(type), &i, sizeof(type)); \
-            return;                                        \
-        }                                                  \
-    } while(0)
-
-static void
-write_raw_complex_data(char *target, Py_complex source, int size)
-{
-    _write_raw_complex_data(float);
-    _write_raw_complex_data(double);
-    Py_FatalError("write_raw_complex_data: bad complex size");
-}
-
-static PyObject *
-new_simple_cdata(char *data, CTypeDescrObject *ct)
-{
-    CDataObject *cd = PyObject_New(CDataObject, &CData_Type);
-    if (cd == NULL)
-        return NULL;
-    Py_INCREF(ct);
-    cd->c_data = data;
-    cd->c_type = ct;
-    cd->c_weakreflist = NULL;
-    return (PyObject *)cd;
-}
-
-static PyObject *
-new_sized_cdata(char *data, CTypeDescrObject *ct, Py_ssize_t length)
-{
-    CDataObject_own_length *scd;
-
-    scd = (CDataObject_own_length *)PyObject_Malloc(
-        offsetof(CDataObject_own_length, alignment));
-    if (PyObject_Init((PyObject *)scd, &CData_Type) == NULL)
-        return NULL;
-    Py_INCREF(ct);
-    scd->head.c_type = ct;
-    scd->head.c_data = data;
-    scd->head.c_weakreflist = NULL;
-    scd->length = length;
-    return (PyObject *)scd;
-}
-
-static CDataObject *_new_casted_primitive(CTypeDescrObject *ct);  /*forward*/
-
-static PyObject *
-convert_to_object(char *data, CTypeDescrObject *ct)
-{
-    if (!(ct->ct_flags & CT_PRIMITIVE_ANY)) {
-        /* non-primitive types (check done just for performance) */
-        if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR)) {
-            char *ptrdata = *(char **)data;
-            /*READ(data, sizeof(char *))*/
-            return new_simple_cdata(ptrdata, ct);
-        }
-        else if (ct->ct_flags & CT_IS_OPAQUE) {
-            PyErr_Format(PyExc_TypeError, "cdata '%s' is opaque",
-                         ct->ct_name);
-            return NULL;
-        }
-        else if (ct->ct_flags & (CT_STRUCT|CT_UNION)) {
-            return new_simple_cdata(data, ct);
-        }
-        else if (ct->ct_flags & CT_ARRAY) {
-            if (ct->ct_length < 0) {
-                /* we can't return a <cdata 'int[]'> here, because we don't
-                   know the length to give it.  As a compromize, returns
-                   <cdata 'int *'> in this case. */
-                ct = (CTypeDescrObject *)ct->ct_stuff;
-            }
-            return new_simple_cdata(data, ct);
-        }
-    }
-    else if (ct->ct_flags & CT_PRIMITIVE_SIGNED) {
-        PY_LONG_LONG value;
-        /*READ(data, ct->ct_size)*/
-        value = read_raw_signed_data(data, ct->ct_size);
-        if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG)
-            return PyInt_FromLong((long)value);
-        else
-            return PyLong_FromLongLong(value);
-    }
-    else if (ct->ct_flags & CT_PRIMITIVE_UNSIGNED) {
-        unsigned PY_LONG_LONG value;
-        /*READ(data, ct->ct_size)*/
-        value = read_raw_unsigned_data(data, ct->ct_size);
-
-        if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG) {
-            if (ct->ct_flags & CT_IS_BOOL) {
-                PyObject *x;
-                switch ((int)value) {
-                case 0: x = Py_False; break;
-                case 1: x = Py_True; break;
-                default:
-                    PyErr_Format(PyExc_ValueError,
-                                 "got a _Bool of value %d, expected 0 or 1",
-                                 (int)value);
-                    return NULL;
-                }
-                Py_INCREF(x);
-                return x;
-            }
-            return PyInt_FromLong((long)value);
-        }
-        else
-            return PyLong_FromUnsignedLongLong(value);
-    }
-    else if (ct->ct_flags & CT_PRIMITIVE_FLOAT) {
-        /*READ(data, ct->ct_size)*/
-        if (!(ct->ct_flags & CT_IS_LONGDOUBLE)) {
-            double value = read_raw_float_data(data, ct->ct_size);
-            return PyFloat_FromDouble(value);
-        }
-        else {
-            long double value = read_raw_longdouble_data(data);
-            CDataObject *cd = _new_casted_primitive(ct);
-            if (cd != NULL)
-                write_raw_longdouble_data(cd->c_data, value);
-            return (PyObject *)cd;
-        }
-    }
-    else if (ct->ct_flags & CT_PRIMITIVE_CHAR) {
-        /*READ(data, ct->ct_size)*/
-        switch (ct->ct_size) {
-        case sizeof(char):
-            return PyBytes_FromStringAndSize(data, 1);
-        case 2:
-            return _my_PyUnicode_FromChar16((cffi_char16_t *)data, 1);
-        case 4:
-            return _my_PyUnicode_FromChar32((cffi_char32_t *)data, 1);
-        }
-    }
-    else if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) {
-        Py_complex value = read_raw_complex_data(data, ct->ct_size);
-        return PyComplex_FromCComplex(value);
-    }
-
-    PyErr_Format(PyExc_SystemError,
-                 "convert_to_object: '%s'", ct->ct_name);
-    return NULL;
-}
-
-static PyObject *
-convert_to_object_bitfield(char *data, CFieldObject *cf)
-{
-    CTypeDescrObject *ct = cf->cf_type;
-    /*READ(data, ct->ct_size)*/
-
-    if (ct->ct_flags & CT_PRIMITIVE_SIGNED) {
-        unsigned PY_LONG_LONG value, valuemask, shiftforsign;
-        PY_LONG_LONG result;
-
-        value = (unsigned PY_LONG_LONG)read_raw_signed_data(data, ct->ct_size);
-        valuemask = (1ULL << cf->cf_bitsize) - 1ULL;
-        shiftforsign = 1ULL << (cf->cf_bitsize - 1);
-        value = ((value >> cf->cf_bitshift) + shiftforsign) & valuemask;
-        result = ((PY_LONG_LONG)value) - (PY_LONG_LONG)shiftforsign;
-
-        if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG)
-            return PyInt_FromLong((long)result);
-        else
-            return PyLong_FromLongLong(result);
-    }
-    else {
-        unsigned PY_LONG_LONG value, valuemask;
-
-        value = read_raw_unsigned_data(data, ct->ct_size);
-        valuemask = (1ULL << cf->cf_bitsize) - 1ULL;
-        value = (value >> cf->cf_bitshift) & valuemask;
-
-        if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG)
-            return PyInt_FromLong((long)value);
-        else
-            return PyLong_FromUnsignedLongLong(value);
-    }
-}
-
-static int _convert_overflow(PyObject *init, const char *ct_name)
-{
-    PyObject *s;
-    if (PyErr_Occurred())   /* already an exception pending */
-        return -1;
-    s = PyObject_Str(init);
-    if (s == NULL)
-        return -1;
-    PyErr_Format(PyExc_OverflowError, "integer %s does not fit '%s'",
-                 PyText_AS_UTF8(s), ct_name);
-    Py_DECREF(s);
-    return -1;
-}
-
-static int _convert_to_char(PyObject *init)
-{
-    if (PyBytes_Check(init) && PyBytes_GET_SIZE(init) == 1) {
-        return (unsigned char)(PyBytes_AS_STRING(init)[0]);
-    }
-    if (CData_Check(init) &&
-           (((CDataObject *)init)->c_type->ct_flags & CT_PRIMITIVE_CHAR) &&
-           (((CDataObject *)init)->c_type->ct_size == sizeof(char))) {
-        char *data = ((CDataObject *)init)->c_data;
-        /*READ(data, 1)*/
-        return *(unsigned char *)data;
-    }
-    PyErr_Format(PyExc_TypeError,
-                 "initializer for ctype 'char' must be a "STR_OR_BYTES
-                 " of length 1, not %.200s", Py_TYPE(init)->tp_name);
-    return -1;
-}
-
-static cffi_char16_t _convert_to_char16_t(PyObject *init)
-{
-    char err_got[80];
-    err_got[0] = 0;
-
-    if (PyUnicode_Check(init)) {
-        cffi_char16_t ordinal;
-        if (_my_PyUnicode_AsSingleChar16(init, &ordinal, err_got) == 0)
-            return ordinal;
-    }
-    if (CData_Check(init) &&
-           (((CDataObject *)init)->c_type->ct_flags & CT_PRIMITIVE_CHAR) &&
-           (((CDataObject *)init)->c_type->ct_size == 2)) {
-        char *data = ((CDataObject *)init)->c_data;
-        /*READ(data, 2)*/
-        return *(cffi_char16_t *)data;
-    }
-    PyErr_Format(PyExc_TypeError,
-                 "initializer for ctype 'char16_t' must be a unicode string "
-                 "of length 1, not %.200s",
-                 err_got[0] == 0 ? Py_TYPE(init)->tp_name : err_got);
-    return (cffi_char16_t)-1;
-}
-
-static cffi_char32_t _convert_to_char32_t(PyObject *init)
-{
-    char err_got[80];
-    err_got[0] = 0;
-
-    if (PyUnicode_Check(init)) {
-        cffi_char32_t ordinal;
-        if (_my_PyUnicode_AsSingleChar32(init, &ordinal, err_got) == 0)
-            return ordinal;
-    }
-    if (CData_Check(init) &&
-           (((CDataObject *)init)->c_type->ct_flags & CT_PRIMITIVE_CHAR) &&
-           (((CDataObject *)init)->c_type->ct_size == 4)) {
-        char *data = ((CDataObject *)init)->c_data;
-        /*READ(data, 4)*/
-        return *(cffi_char32_t *)data;
-    }
-    PyErr_Format(PyExc_TypeError,
-                 "initializer for ctype 'char32_t' must be a unicode string "
-                 "of length 1, not %.200s",
-                 err_got[0] == 0 ? Py_TYPE(init)->tp_name : err_got);
-    return (cffi_char32_t)-1;
-}
-
-static int _convert_error(PyObject *init, CTypeDescrObject *ct,
-                          const char *expected)
-{
-    if (CData_Check(init)) {
-        CTypeDescrObject *ct2 = ((CDataObject *)init)->c_type;
-        if (strcmp(ct->ct_name, ct2->ct_name) != 0)
-            PyErr_Format(PyExc_TypeError,
-                         "initializer for ctype '%s' must be a %s, "
-                         "not cdata '%s'",
-                         ct->ct_name, expected, ct2->ct_name);
-        else if (ct != ct2) {
-            /* in case we'd give the error message "initializer for
-               ctype 'A' must be a pointer to same type, not cdata
-               'B'", but with A=B, then give instead a different error
-               message to try to clear up the confusion */
-            PyErr_Format(PyExc_TypeError,
-                         "initializer for ctype '%s' appears indeed to be '%s',"
-                         " but the types are different (check that you are not"
-                         " e.g. mixing up different ffi instances)",
-                         ct->ct_name, ct2->ct_name);
-        }
-        else
-        {
-            PyErr_Format(PyExc_SystemError,
-                         "initializer for ctype '%s' is correct, but we get "
-                         "an internal mismatch--please report a bug",
-                         ct->ct_name);
-        }
-    }
-    else
-        PyErr_Format(PyExc_TypeError,
-                     "initializer for ctype '%s' must be a %s, "
-                     "not %.200s",
-                     ct->ct_name, expected, Py_TYPE(init)->tp_name);
-    return -1;
-}
-
-static int    /* forward */
-convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init);
-static int    /* forward */
-convert_from_object_bitfield(char *data, CFieldObject *cf, PyObject *init);
-
-static Py_ssize_t
-get_new_array_length(CTypeDescrObject *ctitem, PyObject **pvalue)
-{
-    PyObject *value = *pvalue;
-
-    if (PyList_Check(value) || PyTuple_Check(value)) {
-        return PySequence_Fast_GET_SIZE(value);
-    }
-    else if (PyBytes_Check(value)) {
-        /* from a string, we add the null terminator */
-        return PyBytes_GET_SIZE(value) + 1;
-    }
-    else if (PyUnicode_Check(value)) {
-        /* from a unicode, we add the null terminator */
-        int length;
-        if (ctitem->ct_size == 2)
-            length = _my_PyUnicode_SizeAsChar16(value);
-        else
-            length = _my_PyUnicode_SizeAsChar32(value);
-        return length + 1;
-    }
-    else {
-        Py_ssize_t explicitlength;
-        explicitlength = PyNumber_AsSsize_t(value, PyExc_OverflowError);
-        if (explicitlength < 0) {
-            if (PyErr_Occurred()) {
-                if (PyErr_ExceptionMatches(PyExc_TypeError))
-                    PyErr_Format(PyExc_TypeError,
-                        "expected new array length or list/tuple/str, "
-                        "not %.200s", Py_TYPE(value)->tp_name);
-            }
-            else
-                PyErr_SetString(PyExc_ValueError, "negative array length");
-            return -1;
-        }
-        *pvalue = Py_None;
-        return explicitlength;
-    }
-}
-
-static int
-convert_field_from_object(char *data, CFieldObject *cf, PyObject *value)
-{
-    data += cf->cf_offset;
-    if (cf->cf_bitshift >= 0)
-        return convert_from_object_bitfield(data, cf, value);
-    else
-        return convert_from_object(data, cf->cf_type, value);
-}
-
-static int
-add_varsize_length(Py_ssize_t offset, Py_ssize_t itemsize,
-                   Py_ssize_t varsizelength, Py_ssize_t *optvarsize)
-{
-    /* update '*optvarsize' to account for an array of 'varsizelength'
-       elements, each of size 'itemsize', that starts at 'offset'. */
-    Py_ssize_t size = ADD_WRAPAROUND(offset,
-                              MUL_WRAPAROUND(itemsize, varsizelength));
-    if (size < 0 ||
-        ((size - offset) / itemsize) != varsizelength) {
-        PyErr_SetString(PyExc_OverflowError,
-                        "array size would overflow a Py_ssize_t");
-        return -1;
-    }
-    if (size > *optvarsize)
-        *optvarsize = size;
-    return 0;
-}
-
-static int
-convert_struct_from_object(char *data, CTypeDescrObject *ct, PyObject *init,
-                           Py_ssize_t *optvarsize);  /* forward */
-
-static int
-convert_vfield_from_object(char *data, CFieldObject *cf, PyObject *value,
-                           Py_ssize_t *optvarsize)
-{
-    /* a special case for var-sized C99 arrays */
-    if ((cf->cf_type->ct_flags & CT_ARRAY) && cf->cf_type->ct_size < 0) {
-        Py_ssize_t varsizelength = get_new_array_length(
-                                      cf->cf_type->ct_itemdescr, &value);
-        if (varsizelength < 0)
-            return -1;
-        if (optvarsize != NULL) {
-            /* in this mode, the only purpose of this function is to compute
-               the real size of the structure from a var-sized C99 array */
-            assert(data == NULL);
-            return add_varsize_length(cf->cf_offset,
-                cf->cf_type->ct_itemdescr->ct_size,
-                varsizelength,
-                optvarsize);
-        }
-        /* if 'value' was only an integer, get_new_array_length() returns
-           it and convert 'value' to be None.  Detect if this was the case,
-           and if so, stop here, leaving the content uninitialized
-           (it should be zero-initialized from somewhere else). */
-        if (value == Py_None)
-            return 0;
-    }
-    if (optvarsize == NULL) {
-        return convert_field_from_object(data, cf, value);
-    }
-    else if ((cf->cf_type->ct_flags & CT_WITH_VAR_ARRAY) != 0 &&
-             !CData_Check(value)) {
-        Py_ssize_t subsize = cf->cf_type->ct_size;
-        if (convert_struct_from_object(NULL, cf->cf_type, value, &subsize) < 0)
-            return -1;
-        return add_varsize_length(cf->cf_offset, 1, subsize, optvarsize);
-    }
-    else
-        return 0;
-}
-
-static int
-must_be_array_of_zero_or_one(const char *data, Py_ssize_t n)
-{
-    Py_ssize_t i;
-    for (i = 0; i < n; i++) {
-        if (((unsigned char)data[i]) > 1) {
-            PyErr_SetString(PyExc_ValueError,
-                "an array of _Bool can only contain \\x00 or \\x01");
-            return -1;
-        }
-    }
-    return 0;
-}
-
-static Py_ssize_t
-get_array_length(CDataObject *cd)
-{
-    if (cd->c_type->ct_length < 0)
-        return ((CDataObject_own_length *)cd)->length;
-    else
-        return cd->c_type->ct_length;
-}
-
-static int
-convert_array_from_object(char *data, CTypeDescrObject *ct, PyObject *init)
-{
-    /* used by convert_from_object(), and also to decode lists/tuples/unicodes
-       passed as function arguments.  'ct' is an CT_ARRAY in the first case
-       and a CT_POINTER in the second case. */
-    const char *expected;
-    CTypeDescrObject *ctitem = ct->ct_itemdescr;
-
-    if (PyList_Check(init) || PyTuple_Check(init)) {
-        PyObject **items;
-        Py_ssize_t i, n;
-        n = PySequence_Fast_GET_SIZE(init);
-        if (ct->ct_length >= 0 && n > ct->ct_length) {
-            PyErr_Format(PyExc_IndexError,
-                         "too many initializers for '%s' (got %zd)",
-                         ct->ct_name, n);
-            return -1;
-        }
-        items = PySequence_Fast_ITEMS(init);
-        for (i=0; i<n; i++) {
-            if (convert_from_object(data, ctitem, items[i]) < 0)
-                return -1;
-            data += ctitem->ct_size;
-        }
-        return 0;
-    }
-    else if ((ctitem->ct_flags & CT_PRIMITIVE_CHAR) ||
-             ((ctitem->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED))
-              && (ctitem->ct_size == sizeof(char)))) {
-        if (ctitem->ct_size == sizeof(char)) {
-            char *srcdata;
-            Py_ssize_t n;
-            if (!PyBytes_Check(init)) {
-                expected = STR_OR_BYTES" or list or tuple";
-                goto cannot_convert;
-            }
-            n = PyBytes_GET_SIZE(init);
-            if (ct->ct_length >= 0 && n > ct->ct_length) {
-                PyErr_Format(PyExc_IndexError,
-                             "initializer "STR_OR_BYTES" is too long for '%s' "
-                             "(got %zd characters)", ct->ct_name, n);
-                return -1;
-            }
-            if (n != ct->ct_length)
-                n++;
-            srcdata = PyBytes_AS_STRING(init);
-            if (ctitem->ct_flags & CT_IS_BOOL)
-                if (must_be_array_of_zero_or_one(srcdata, n) < 0)
-                    return -1;
-            memcpy(data, srcdata, n);
-            return 0;
-        }
-        else {
-            Py_ssize_t n;
-            if (!PyUnicode_Check(init)) {
-                expected = "unicode or list or tuple";
-                goto cannot_convert;
-            }
-
-            if (ctitem->ct_size == 4)
-                n = _my_PyUnicode_SizeAsChar32(init);
-            else
-                n = _my_PyUnicode_SizeAsChar16(init);
-
-            if (ct->ct_length >= 0 && n > ct->ct_length) {
-                PyErr_Format(PyExc_IndexError,
-                             "initializer unicode is too long for '%s' "
-                             "(got %zd characters)", ct->ct_name, n);
-                return -1;
-            }
-            if (n != ct->ct_length)
-                n++;
-            if (ctitem->ct_size == 4)
-                return _my_PyUnicode_AsChar32(init, (cffi_char32_t *)data, n);
-            else
-                return _my_PyUnicode_AsChar16(init, (cffi_char16_t *)data, n);
-        }
-    }
-    else {
-        expected = "list or tuple";
-        goto cannot_convert;
-    }
-
- cannot_convert:
-    if ((ct->ct_flags & CT_ARRAY) && CData_Check(init))
-    {
-        CDataObject *cd = (CDataObject *)init;
-        if (cd->c_type == ct)
-        {
-            Py_ssize_t n = get_array_length(cd);
-            memcpy(data, cd->c_data, n * ctitem->ct_size);
-            return 0;
-        }
-    }
-    return _convert_error(init, ct, expected);
-}
-
-static int
-convert_struct_from_object(char *data, CTypeDescrObject *ct, PyObject *init,
-                           Py_ssize_t *optvarsize)
-{
-    /* does not accept 'init' being already a CData */
-    const char *expected;
-
-    if (force_lazy_struct(ct) <= 0) {
-        if (!PyErr_Occurred())
-            PyErr_Format(PyExc_TypeError, "'%s' is opaque", ct->ct_name);
-        return -1;
-    }
-
-    if (PyList_Check(init) || PyTuple_Check(init)) {
-        PyObject **items = PySequence_Fast_ITEMS(init);
-        Py_ssize_t i, n = PySequence_Fast_GET_SIZE(init);
-        CFieldObject *cf = (CFieldObject *)ct->ct_extra;
-
-        for (i=0; i<n; i++) {
-            while (cf != NULL && (cf->cf_flags & BF_IGNORE_IN_CTOR))
-                cf = cf->cf_next;
-            if (cf == NULL) {
-                PyErr_Format(PyExc_ValueError,
-                             "too many initializers for '%s' (got %zd)",
-                             ct->ct_name, n);
-                return -1;
-            }
-            if (convert_vfield_from_object(data, cf, items[i], optvarsize) < 0)
-                return -1;
-            cf = cf->cf_next;
-        }
-        return 0;
-    }
-    if (PyDict_Check(init)) {
-        PyObject *d_key, *d_value;
-        Py_ssize_t i = 0;
-        CFieldObject *cf;
-
-        while (PyDict_Next(init, &i, &d_key, &d_value)) {
-            cf = (CFieldObject *)PyDict_GetItem(ct->ct_stuff, d_key);
-            if (cf == NULL) {
-                PyErr_SetObject(PyExc_KeyError, d_key);
-                return -1;
-            }
-            if (convert_vfield_from_object(data, cf, d_value, optvarsize) < 0)
-                return -1;
-        }
-        return 0;
-    }
-    expected = optvarsize == NULL ? "list or tuple or dict or struct-cdata"
-                                  : "list or tuple or dict";
-    return _convert_error(init, ct, expected);
-}
-
-#ifdef __GNUC__
-# if __GNUC__ >= 4
-/* Don't go inlining this huge function.  Needed because occasionally
-   it gets inlined in places where is causes a warning: call to
-   __builtin___memcpy_chk will always overflow destination buffer
-   (which is places where the 'ct' should never represent such a large
-   primitive type anyway). */
-__attribute__((noinline))
-# endif
-#endif
-static int
-convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init)
-{
-    const char *expected;
-    char buf[sizeof(PY_LONG_LONG)];
-
-    /*if (ct->ct_size > 0)*/
-        /*WRITE(data, ct->ct_size)*/
-
-    if (ct->ct_flags & CT_ARRAY) {
-        return convert_array_from_object(data, ct, init);
-    }
-    if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR)) {
-        char *ptrdata;
-        CTypeDescrObject *ctinit;
-
-        if (!CData_Check(init)) {
-            expected = "cdata pointer";
-            goto cannot_convert;
-        }
-        ctinit = ((CDataObject *)init)->c_type;
-        if (!(ctinit->ct_flags & (CT_POINTER|CT_FUNCTIONPTR))) {
-            if (ctinit->ct_flags & CT_ARRAY)
-                ctinit = (CTypeDescrObject *)ctinit->ct_stuff;
-            else {
-                expected = "pointer or array";
-                goto cannot_convert;
-            }
-        }
-        if (ctinit != ct) {
-            int combined_flags = ct->ct_flags | ctinit->ct_flags;
-            if (combined_flags & CT_IS_VOID_PTR)
-                ;   /* accept "void *" as either source or target */
-            else if (combined_flags & CT_IS_VOIDCHAR_PTR) {
-                /* for backward compatibility, accept "char *" as either
-                   source of target.  This is not what C does, though,
-                   so emit a warning that will eventually turn into an
-                   error.  The warning is turned off if both types are
-                   pointers to single bytes. */
-                char *msg = (ct->ct_flags & CT_IS_VOIDCHAR_PTR ?
-                    "implicit cast to 'char *' from a different pointer type: "
-                    "will be forbidden in the future (check that the types "
-                    "are as you expect; use an explicit ffi.cast() if they "
-                    "are correct)" :
-                    "implicit cast from 'char *' to a different pointer type: "
-                    "will be forbidden in the future (check that the types "
-                    "are as you expect; use an explicit ffi.cast() if they "
-                    "are correct)");
-                if ((ct->ct_flags & ctinit->ct_flags & CT_POINTER) &&
-                    ct->ct_itemdescr->ct_size == 1 &&
-                    ctinit->ct_itemdescr->ct_size == 1) {
-                    /* no warning */
-                }
-                else if (PyErr_WarnEx(PyExc_UserWarning, msg, 1))
-                    return -1;
-            }
-            else {
-                expected = "pointer to same type";
-                goto cannot_convert;
-            }
-        }
-        ptrdata = ((CDataObject *)init)->c_data;
-
-        *(char **)data = ptrdata;
-        return 0;
-    }
-    if (ct->ct_flags & CT_PRIMITIVE_SIGNED) {
-        PY_LONG_LONG value = _my_PyLong_AsLongLong(init);
-        if (value == -1 && PyErr_Occurred())
-            return -1;
-        write_raw_integer_data(buf, value, ct->ct_size);
-        if (value != read_raw_signed_data(buf, ct->ct_size))
-            goto overflow;
-        write_raw_integer_data(data, value, ct->ct_size);
-        return 0;
-    }
-    if (ct->ct_flags & CT_PRIMITIVE_UNSIGNED) {
-        unsigned PY_LONG_LONG value = _my_PyLong_AsUnsignedLongLong(init, 1);
-        if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
-            return -1;
-        if (ct->ct_flags & CT_IS_BOOL) {
-            if (value > 1ULL)      /* value != 0 && value != 1 */
-                goto overflow;
-        }
-        else {
-            write_raw_integer_data(buf, value, ct->ct_size);
-            if (value != read_raw_unsigned_data(buf, ct->ct_size))
-                goto overflow;
-        }
-        write_raw_integer_data(data, value, ct->ct_size);
-        return 0;
-    }
-    if (ct->ct_flags & CT_PRIMITIVE_FLOAT) {
-        double value;
-        if ((ct->ct_flags & CT_IS_LONGDOUBLE) &&
-                CData_Check(init) &&
-                (((CDataObject *)init)->c_type->ct_flags & CT_IS_LONGDOUBLE)) {
-            long double lvalue;
-            char *initdata = ((CDataObject *)init)->c_data;
-            /*READ(initdata, sizeof(long double))*/
-            lvalue = read_raw_longdouble_data(initdata);
-            write_raw_longdouble_data(data, lvalue);
-            return 0;
-        }
-        value = PyFloat_AsDouble(init);
-        if (value == -1.0 && PyErr_Occurred())
-            return -1;
-        if (!(ct->ct_flags & CT_IS_LONGDOUBLE))
-            write_raw_float_data(data, value, ct->ct_size);
-        else
-            write_raw_longdouble_data(data, (long double)value);
-        return 0;
-    }
-    if (ct->ct_flags & CT_PRIMITIVE_CHAR) {
-        switch (ct->ct_size) {
-        case sizeof(char): {
-            int res = _convert_to_char(init);
-            if (res < 0)
-                return -1;
-            data[0] = res;
-            return 0;
-        }
-        case 2: {
-            cffi_char16_t res = _convert_to_char16_t(init);
-            if (res == (cffi_char16_t)-1 && PyErr_Occurred())
-                return -1;
-            *(cffi_char16_t *)data = res;
-            return 0;
-        }
-        case 4: {
-            cffi_char32_t res = _convert_to_char32_t(init);
-            if (res == (cffi_char32_t)-1 && PyErr_Occurred())
-                return -1;
-            *(cffi_char32_t *)data = res;
-            return 0;
-        }
-        }
-    }
-    if (ct->ct_flags & (CT_STRUCT|CT_UNION)) {
-
-        if (CData_Check(init)) {
-            if (((CDataObject *)init)->c_type == ct && ct->ct_size >= 0) {
-                memcpy(data, ((CDataObject *)init)->c_data, ct->ct_size);
-                return 0;
-            }
-        }
-        return convert_struct_from_object(data, ct, init, NULL);
-    }
-    if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) {
-        Py_complex value = PyComplex_AsCComplex(init);
-        if (PyErr_Occurred())
-            return -1;
-        write_raw_complex_data(data, value, ct->ct_size);
-        return 0;
-    }
-    PyErr_Format(PyExc_SystemError,
-                 "convert_from_object: '%s'", ct->ct_name);
-    return -1;
-
- overflow:
-    return _convert_overflow(init, ct->ct_name);
-
- cannot_convert:
-    return _convert_error(init, ct, expected);
-}
-
-static int
-convert_from_object_bitfield(char *data, CFieldObject *cf, PyObject *init)
-{
-    CTypeDescrObject *ct = cf->cf_type;
-    PY_LONG_LONG fmin, fmax, value = PyLong_AsLongLong(init);
-    unsigned PY_LONG_LONG rawfielddata, rawvalue, rawmask;
-    if (value == -1 && PyErr_Occurred())
-        return -1;
-
-    if (ct->ct_flags & CT_PRIMITIVE_SIGNED) {
-        fmin = -(1LL << (cf->cf_bitsize-1));
-        fmax = (1LL << (cf->cf_bitsize-1)) - 1LL;
-        if (fmax == 0)
-            fmax = 1;    /* special case to let "int x:1" receive "1" */
-    }
-    else {
-        fmin = 0LL;
-        fmax = (PY_LONG_LONG)((1ULL << cf->cf_bitsize) - 1ULL);
-    }
-    if (value < fmin || value > fmax) {
-        /* phew, PyErr_Format does not support "%lld" in Python 2.6 */
-        PyObject *svalue = NULL, *sfmin = NULL, *sfmax = NULL;
-        PyObject *lfmin = NULL, *lfmax = NULL;
-        svalue = PyObject_Str(init);
-        if (svalue == NULL) goto skip;
-        lfmin = PyLong_FromLongLong(fmin);
-        if (lfmin == NULL) goto skip;
-        sfmin = PyObject_Str(lfmin);
-        if (sfmin == NULL) goto skip;
-        lfmax = PyLong_FromLongLong(fmax);
-        if (lfmax == NULL) goto skip;
-        sfmax = PyObject_Str(lfmax);
-        if (sfmax == NULL) goto skip;
-        PyErr_Format(PyExc_OverflowError,
-                     "value %s outside the range allowed by the "
-                     "bit field width: %s <= x <= %s",
-                     PyText_AS_UTF8(svalue),
-                     PyText_AS_UTF8(sfmin),
-                     PyText_AS_UTF8(sfmax));
-       skip:
-        Py_XDECREF(svalue);
-        Py_XDECREF(sfmin);
-        Py_XDECREF(sfmax);
-        Py_XDECREF(lfmin);
-        Py_XDECREF(lfmax);
-        return -1;
-    }
-
-    rawmask = ((1ULL << cf->cf_bitsize) - 1ULL) << cf->cf_bitshift;
-    rawvalue = ((unsigned PY_LONG_LONG)value) << cf->cf_bitshift;
-    /*WRITE(data, ct->ct_size)*/
-    rawfielddata = read_raw_unsigned_data(data, ct->ct_size);
-    rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask);
-    write_raw_integer_data(data, rawfielddata, ct->ct_size);
-    return 0;
-}
-
-static int
-get_alignment(CTypeDescrObject *ct)
-{
-    int align;
- retry:
-    if ((ct->ct_flags & (CT_PRIMITIVE_ANY|CT_STRUCT|CT_UNION)) &&
-        !(ct->ct_flags & CT_IS_OPAQUE)) {
-        align = ct->ct_length;
-        if (align == -1 && (ct->ct_flags & CT_LAZY_FIELD_LIST)) {
-            force_lazy_struct(ct);
-            align = ct->ct_length;
-        }
-    }
-    else if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR)) {
-        struct aligncheck_ptr { char x; char *y; };
-        align = offsetof(struct aligncheck_ptr, y);
-    }
-    else if (ct->ct_flags & CT_ARRAY) {
-        ct = ct->ct_itemdescr;
-        goto retry;
-    }
-    else {
-        PyErr_Format(PyExc_ValueError, "ctype '%s' is of unknown alignment",
-                     ct->ct_name);
-        return -1;
-    }
-
-    if ((align < 1) || (align & (align-1))) {
-        PyErr_Format(PyExc_SystemError,
-                     "found for ctype '%s' bogus alignment '%d'",
-                     ct->ct_name, align);
-        return -1;
-    }
-    return align;
-}
-
-static void cdata_dealloc(CDataObject *cd)
-{
-    if (cd->c_weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) cd);
-
-    Py_DECREF(cd->c_type);
-#ifndef CFFI_MEM_LEAK     /* never release anything, tests only */
-    Py_TYPE(cd)->tp_free((PyObject *)cd);
-#endif
-}
-
-static void cdataowning_dealloc(CDataObject *cd)
-{
-    assert(!(cd->c_type->ct_flags & (CT_IS_VOID_PTR | CT_FUNCTIONPTR)));
-
-    if (cd->c_type->ct_flags & CT_IS_PTR_TO_OWNED) {
-        /* for ffi.new("struct *") */
-        Py_DECREF(((CDataObject_own_structptr *)cd)->structobj);
-    }
-#if defined(CFFI_MEM_DEBUG) || defined(CFFI_MEM_LEAK)
-    if (cd->c_type->ct_flags & (CT_PRIMITIVE_ANY | CT_STRUCT | CT_UNION)) {
-        assert(cd->c_type->ct_size >= 0);
-        memset(cd->c_data, 0xDD, cd->c_type->ct_size);
-    }
-    else if (cd->c_type->ct_flags & CT_ARRAY) {
-        Py_ssize_t x = get_array_length(cd);
-        assert(x >= 0);
-        x *= cd->c_type->ct_itemdescr->ct_size;
-        assert(x >= 0);
-        memset(cd->c_data, 0xDD, x);
-    }
-#endif
-    cdata_dealloc(cd);
-}
-
-static void cdataowninggc_dealloc(CDataObject *cd)
-{
-    PyObject_GC_UnTrack(cd);
-
-    if (cd->c_type->ct_flags & CT_IS_VOID_PTR) {        /* a handle */
-        PyObject *x = ((CDataObject_own_structptr *)cd)->structobj;
-        Py_DECREF(x);
-    }
-    else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {   /* a callback */
-        ffi_closure *closure = ((CDataObject_closure *)cd)->closure;
-        PyObject *args = (PyObject *)(closure->user_data);
-        Py_XDECREF(args);
-#if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE
-        if (CFFI_CHECK_FFI_CLOSURE_ALLOC) {
-            ffi_closure_free(closure);
-        } else
-#endif
-            cffi_closure_free(closure);
-    }
-    else {
-        Py_FatalError("cdata CDataOwningGC_Type with unexpected type flags");
-    }
-    cdata_dealloc(cd);
-}
-
-static void cdatafrombuf_dealloc(CDataObject *cd)
-{
-    Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview;
-    cdata_dealloc(cd);
-
-    PyBuffer_Release(view);
-    PyObject_Free(view);
-}
-
-static int cdataowninggc_traverse(CDataObject *cd, visitproc visit, void *arg)
-{
-    if (cd->c_type->ct_flags & CT_IS_VOID_PTR) {        /* a handle */
-        PyObject *x = ((CDataObject_own_structptr *)cd)->structobj;
-        Py_VISIT(x);
-    }
-    else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {   /* a callback */
-        ffi_closure *closure = ((CDataObject_closure *)cd)->closure;
-        PyObject *args = (PyObject *)(closure->user_data);
-        Py_VISIT(args);
-    }
-    return 0;
-}
-
-static int cdatafrombuf_traverse(CDataObject *cd, visitproc visit, void *arg)
-{
-    Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview;
-    Py_VISIT(view->obj);
-    return 0;
-}
-
-static int cdataowninggc_clear(CDataObject *cd)
-{
-    if (cd->c_type->ct_flags & CT_IS_VOID_PTR) {        /* a handle */
-        CDataObject_own_structptr *cd1 = (CDataObject_own_structptr *)cd;
-        PyObject *x = cd1->structobj;
-        Py_INCREF(Py_None);
-        cd1->structobj = Py_None;
-        Py_DECREF(x);
-    }
-    else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {   /* a callback */
-        ffi_closure *closure = ((CDataObject_closure *)cd)->closure;
-        PyObject *args = (PyObject *)(closure->user_data);
-        closure->user_data = NULL;
-        Py_XDECREF(args);
-    }
-    return 0;
-}
-
-static int cdatafrombuf_clear(CDataObject *cd)
-{
-    Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview;
-    PyBuffer_Release(view);
-    return 0;
-}
-
-/* forward */
-static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb,
-                                      char *objdescr, PyObject *obj,
-                                      char *extra_error_line);
-
-
-static void gcp_finalize(PyObject *destructor, PyObject *origobj)
-{
-    /* NOTE: this decrements the reference count of the two arguments */
-
-    if (destructor != NULL) {
-        PyObject *result;
-        PyObject *error_type, *error_value, *error_traceback;
-
-        /* Save the current exception */
-        PyErr_Fetch(&error_type, &error_value, &error_traceback);
-
-        result = PyObject_CallFunctionObjArgs(destructor, origobj, NULL);
-        if (result != NULL) {
-            Py_DECREF(result);
-        }
-        else {
-            PyObject *t, *v, *tb;
-            PyErr_Fetch(&t, &v, &tb);
-            /* Don't use error capture here, because it is very much
-             * like errors at __del__(), and these ones are not captured
-             * either */
-            /* ecap = _cffi_start_error_capture(); */
-            _my_PyErr_WriteUnraisable(t, v, tb, "From callback for ffi.gc ",
-                                      origobj, NULL);
-            /* _cffi_stop_error_capture(ecap); */
-        }
-        Py_DECREF(destructor);
-
-        /* Restore the saved exception */
-        PyErr_Restore(error_type, error_value, error_traceback);
-    }
-    Py_XDECREF(origobj);
-}
-
-static void cdatagcp_finalize(CDataObject_gcp *cd)
-{
-    PyObject *destructor = cd->destructor;
-    PyObject *origobj = cd->origobj;
-    cd->destructor = NULL;
-    cd->origobj = NULL;
-    gcp_finalize(destructor, origobj);
-}
-
-static void cdatagcp_dealloc(CDataObject_gcp *cd)
-{
-    PyObject *destructor = cd->destructor;
-    PyObject *origobj = cd->origobj;
-    cdata_dealloc((CDataObject *)cd);
-
-    gcp_finalize(destructor, origobj);
-}
-
-static int cdatagcp_traverse(CDataObject_gcp *cd, visitproc visit, void *arg)
-{
-    Py_VISIT(cd->destructor);
-    Py_VISIT(cd->origobj);
-    return 0;
-}
-
-static PyObject *cdata_float(CDataObject *cd);  /*forward*/
-
-static PyObject *convert_cdata_to_enum_string(CDataObject *cd, int both)
-{
-    PyObject *d_key, *d_value;
-    CTypeDescrObject *ct = cd->c_type;
-
-    assert(ct->ct_flags & CT_IS_ENUM);
-    d_key = convert_to_object(cd->c_data, ct);
-    if (d_key == NULL)
-        return NULL;
-
-    d_value = PyDict_GetItem(PyTuple_GET_ITEM(ct->ct_stuff, 1), d_key);
-    if (d_value != NULL) {
-        if (both) {
-            PyObject *o = PyObject_Str(d_key);
-            if (o == NULL)
-                d_value = NULL;
-            else {
-                d_value = PyText_FromFormat("%s: %s",
-                                            PyText_AS_UTF8(o),
-                                            PyText_AS_UTF8(d_value));
-                Py_DECREF(o);
-            }
-        }
-        else
-            Py_INCREF(d_value);
-    }
-    else
-        d_value = PyObject_Str(d_key);
-    Py_DECREF(d_key);
-    return d_value;
-}
-
-static PyObject *cdata_repr(CDataObject *cd)
-{
-    char *extra;
-    PyObject *result, *s;
-
-    if (cd->c_type->ct_flags & CT_PRIMITIVE_ANY) {
-        if (cd->c_type->ct_flags & CT_IS_ENUM) {
-            s = convert_cdata_to_enum_string(cd, 1);
-        }
-        else if (cd->c_type->ct_flags & CT_IS_LONGDOUBLE) {
-            long double lvalue;
-            char buffer[128];   /* big enough */
-            /*READ(cd->c_data, sizeof(long double)*/
-            lvalue = read_raw_longdouble_data(cd->c_data);
-            sprintf(buffer, "%LE", lvalue);
-            s = PyText_FromString(buffer);
-        }
-        else {
-            PyObject *o = convert_to_object(cd->c_data, cd->c_type);
-            if (o == NULL)
-                return NULL;
-            s = PyObject_Repr(o);
-            Py_DECREF(o);
-        }
-    }
-    else if ((cd->c_type->ct_flags & CT_ARRAY) && cd->c_type->ct_length < 0) {
-        s = PyText_FromFormat("sliced length %zd", get_array_length(cd));
-    }
-    else {
-        if (cd->c_data != NULL) {
-            s = PyText_FromFormat("%p", cd->c_data);
-        }
-        else
-            s = PyText_FromString("NULL");
-    }
-    if (s == NULL)
-        return NULL;
-    /* it's slightly confusing to get "<cdata 'struct foo' 0x...>" because the
-       struct foo is not owned.  Trying to make it clearer, write in this
-       case "<cdata 'struct foo &' 0x...>". */
-    if (cd->c_type->ct_flags & (CT_STRUCT|CT_UNION))
-        extra = " &";
-    else
-        extra = "";
-    result = PyText_FromFormat("<cdata '%s%s' %s>",
-                               cd->c_type->ct_name, extra,
-                               PyText_AsUTF8(s));
-    Py_DECREF(s);
-    return result;
-}
-
-static PyObject *_cdata_repr2(CDataObject *cd, char *text, PyObject *x)
-{
-    PyObject *res, *s = PyObject_Repr(x);
-    if (s == NULL)
-        return NULL;
-    res = PyText_FromFormat("<cdata '%s' %s %s>",
-                            cd->c_type->ct_name, text, PyText_AsUTF8(s));
-    Py_DECREF(s);
-    return res;
-}
-
-static Py_ssize_t _cdata_var_byte_size(CDataObject *cd)
-{
-    /* If 'cd' is a 'struct foo' or 'struct foo *' allocated with
-       ffi.new(), and if the struct foo contains a varsize array,
-       then return the real allocated size.  Otherwise, return -1. */
-    if (!CDataOwn_Check(cd))
-        return -1;
-
-    if (cd->c_type->ct_flags & CT_IS_PTR_TO_OWNED) {
-        cd = (CDataObject *)((CDataObject_own_structptr *)cd)->structobj;
-    }
-    if (cd->c_type->ct_flags & CT_WITH_VAR_ARRAY) {
-        return ((CDataObject_own_length *)cd)->length;
-    }
-    return -1;
-}
-
-static PyObject *_frombuf_repr(CDataObject *cd, const char *cd_type_name)
-{
-    Py_buffer *view = ((CDataObject_frombuf *)cd)->bufferview;
-    const char *obj_tp_name;
-    if (view->obj == NULL) {
-        return PyText_FromFormat(
-            "<cdata '%s' buffer RELEASED>",
-            cd_type_name);
-    }
-
-    obj_tp_name = Py_TYPE(view->obj)->tp_name;
-    if (cd->c_type->ct_flags & CT_ARRAY)
-    {
-        Py_ssize_t buflen = get_array_length(cd);
-        return PyText_FromFormat(
-            "<cdata '%s' buffer len %zd from '%.200s' object>",
-            cd_type_name,
-            buflen,
-            obj_tp_name);
-    }
-    else
-    {
-        return PyText_FromFormat(
-            "<cdata '%s' buffer from '%.200s' object>",
-            cd_type_name,
-            obj_tp_name);
-    }
-}
-
-static PyObject *cdataowning_repr(CDataObject *cd)
-{
-    Py_ssize_t size = _cdata_var_byte_size(cd);
-    if (size < 0) {
-        if (cd->c_type->ct_flags & CT_POINTER)
-            size = cd->c_type->ct_itemdescr->ct_size;
-        else if (cd->c_type->ct_flags & CT_ARRAY)
-            size = get_array_length(cd) * cd->c_type->ct_itemdescr->ct_size;
-        else
-            size = cd->c_type->ct_size;
-    }
-    return PyText_FromFormat("<cdata '%s' owning %zd bytes>",
-                             cd->c_type->ct_name, size);
-}
-
-static PyObject *cdataowninggc_repr(CDataObject *cd)
-{
-    if (cd->c_type->ct_flags & CT_IS_VOID_PTR) {        /* a handle */
-        PyObject *x = ((CDataObject_own_structptr *)cd)->structobj;
-        return _cdata_repr2(cd, "handle to", x);
-    }
-    else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {   /* a callback */
-        ffi_closure *closure = ((CDataObject_closure *)cd)->closure;
-        PyObject *args = (PyObject *)closure->user_data;
-        if (args == NULL)
-            return cdata_repr(cd);
-        else
-            return _cdata_repr2(cd, "calling", PyTuple_GET_ITEM(args, 1));
-    }
-    return cdataowning_repr(cd);   /* but should be unreachable */
-}
-
-static PyObject *cdatafrombuf_repr(CDataObject *cd)
-{
-    return _frombuf_repr(cd, cd->c_type->ct_name);
-}
-
-static int cdata_nonzero(CDataObject *cd)
-{
-    if (cd->c_type->ct_flags & CT_PRIMITIVE_ANY) {
-        if (cd->c_type->ct_flags & (CT_PRIMITIVE_SIGNED |
-                                    CT_PRIMITIVE_UNSIGNED |
-                                    CT_PRIMITIVE_CHAR))
-            return read_raw_unsigned_data(cd->c_data, cd->c_type->ct_size) != 0;
-
-        if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) {
-            if (cd->c_type->ct_flags & CT_IS_LONGDOUBLE)
-                return read_raw_longdouble_data(cd->c_data) != 0.0;
-            return read_raw_float_data(cd->c_data, cd->c_type->ct_size) != 0.0;
-        }
-        if (cd->c_type->ct_flags & CT_PRIMITIVE_COMPLEX) {
-            Py_complex value = read_raw_complex_data(cd->c_data,
-                                                     cd->c_type->ct_size);
-            return value.real != 0.0 || value.imag != 0.0;
-        }
-    }
-    return cd->c_data != NULL;
-}
-
-static PyObject *cdata_int(CDataObject *cd)
-{
-    if ((cd->c_type->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_FITS_LONG))
-                             == (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_FITS_LONG)) {
-        /* this case is to handle enums, but also serves as a slight
-           performance improvement for some other primitive types */
-        long value;
-        /*READ(cd->c_data, cd->c_type->ct_size)*/
-        value = (long)read_raw_signed_data(cd->c_data, cd->c_type->ct_size);
-        return PyInt_FromLong(value);
-    }
-    if (cd->c_type->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED)) {
-        PyObject *result = convert_to_object(cd->c_data, cd->c_type);
-        if (result != NULL && PyBool_Check(result))
-            result = PyInt_FromLong(PyInt_AsLong(result));
-        return result;
-    }
-    else if (cd->c_type->ct_flags & CT_PRIMITIVE_CHAR) {
-        /*READ(cd->c_data, cd->c_type->ct_size)*/
-        switch (cd->c_type->ct_size) {
-        case sizeof(char):
-            return PyInt_FromLong((unsigned char)cd->c_data[0]);
-        case 2:
-            return PyInt_FromLong((long)*(cffi_char16_t *)cd->c_data);
-        case 4:
-            if (cd->c_type->ct_flags & CT_IS_SIGNED_WCHAR)
-                return PyInt_FromLong((long)*(int32_t *)cd->c_data);
-            else if (sizeof(long) > 4)
-                return PyInt_FromLong(*(uint32_t *)cd->c_data);
-            else
-                return PyLong_FromUnsignedLong(*(uint32_t *)cd->c_data);
-        }
-    }
-    else if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) {
-        PyObject *o = cdata_float(cd);
-#if PY_MAJOR_VERSION < 3
-        PyObject *r = o ? PyNumber_Int(o) : NULL;
-#else
-        PyObject *r = o ? PyNumber_Long(o) : NULL;
-#endif
-        Py_XDECREF(o);
-        return r;
-    }
-    PyErr_Format(PyExc_TypeError, "int() not supported on cdata '%s'",
-                 cd->c_type->ct_name);
-    return NULL;
-}
-
-#if PY_MAJOR_VERSION < 3
-static PyObject *cdata_long(CDataObject *cd)
-{
-    PyObject *res = cdata_int(cd);
-    if (res != NULL && PyInt_CheckExact(res)) {
-        PyObject *o = PyLong_FromLong(PyInt_AS_LONG(res));
-        Py_DECREF(res);
-        res = o;
-    }
-    return res;
-}
-#endif
-
-static PyObject *cdata_float(CDataObject *cd)
-{
-    if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) {
-        double value;
-        /*READ(cd->c_data, cd->c_type->ct_size)*/
-        if (!(cd->c_type->ct_flags & CT_IS_LONGDOUBLE)) {
-            value = read_raw_float_data(cd->c_data, cd->c_type->ct_size);
-        }
-        else {
-            value = (double)read_raw_longdouble_data(cd->c_data);
-        }
-        return PyFloat_FromDouble(value);
-    }
-    PyErr_Format(PyExc_TypeError, "float() not supported on cdata '%s'",
-                 cd->c_type->ct_name);
-    return NULL;
-}
-
-static PyObject *cdata_richcompare(PyObject *v, PyObject *w, int op)
-{
-    int v_is_ptr, w_is_ptr;
-    PyObject *pyres;
-
-    assert(CData_Check(v));
-
-    /* Comparisons involving a primitive cdata work differently than
-     * comparisons involving a struct/array/pointer.
-     *
-     * If v or w is a struct/array/pointer, then the other must be too
-     * (otherwise we return NotImplemented and leave the case to
-     * Python).  If both are, then we compare the addresses.
-     *
-     * If v and/or w is a primitive cdata, then we convert the cdata(s)
-     * to regular Python objects and redo the comparison there.
-     */
-
-    v_is_ptr = !(((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY);
-    w_is_ptr = CData_Check(w) &&
-                  !(((CDataObject *)w)->c_type->ct_flags & CT_PRIMITIVE_ANY);
-
-    if (v_is_ptr && w_is_ptr) {
-        int res;
-        char *v_cdata = ((CDataObject *)v)->c_data;
-        char *w_cdata = ((CDataObject *)w)->c_data;
-
-        switch (op) {
-        case Py_EQ: res = (v_cdata == w_cdata); break;
-        case Py_NE: res = (v_cdata != w_cdata); break;
-        case Py_LT: res = (v_cdata <  w_cdata); break;
-        case Py_LE: res = (v_cdata <= w_cdata); break;
-        case Py_GT: res = (v_cdata >  w_cdata); break;
-        case Py_GE: res = (v_cdata >= w_cdata); break;
-        default: res = -1;
-        }
-        pyres = res ? Py_True : Py_False;
-    }
-    else if (v_is_ptr || w_is_ptr) {
-        pyres = Py_NotImplemented;
-    }
-    else {
-        PyObject *aa[2];
-        int i;
-
-        aa[0] = v; Py_INCREF(v);
-        aa[1] = w; Py_INCREF(w);
-        pyres = NULL;
-
-        for (i = 0; i < 2; i++) {
-            v = aa[i];
-            if (!CData_Check(v))
-                continue;
-            w = convert_to_object(((CDataObject *)v)->c_data,
-                                  ((CDataObject *)v)->c_type);
-            if (w == NULL)
-                goto error;
-            if (CData_Check(w)) {
-                Py_DECREF(w);
-                PyErr_Format(PyExc_NotImplementedError,
-                             "cannot use <cdata '%s'> in a comparison",
-                             ((CDataObject *)v)->c_type->ct_name);
-                goto error;
-            }
-            aa[i] = w;
-            Py_DECREF(v);
-        }
-        pyres = PyObject_RichCompare(aa[0], aa[1], op);
-     error:
-        Py_DECREF(aa[1]);
-        Py_DECREF(aa[0]);
-        return pyres;
-    }
-
-    Py_INCREF(pyres);
-    return pyres;
-}
-
-#if PY_MAJOR_VERSION < 3
-typedef long Py_hash_t;
-#endif
-
-static Py_hash_t cdata_hash(PyObject *v)
-{
-    if (((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY) {
-        PyObject *vv = convert_to_object(((CDataObject *)v)->c_data,
-                                         ((CDataObject *)v)->c_type);
-        if (vv == NULL)
-            return -1;
-        if (!CData_Check(vv)) {
-            Py_hash_t hash = PyObject_Hash(vv);
-            Py_DECREF(vv);
-            return hash;
-        }
-        Py_DECREF(vv);
-    }
-    return _Py_HashPointer(((CDataObject *)v)->c_data);
-}
-
-static Py_ssize_t
-cdata_length(CDataObject *cd)
-{
-    if (cd->c_type->ct_flags & CT_ARRAY) {
-        return get_array_length(cd);
-    }
-    PyErr_Format(PyExc_TypeError, "cdata of type '%s' has no len()",
-                 cd->c_type->ct_name);
-    return -1;
-}
-
-static char *
-_cdata_get_indexed_ptr(CDataObject *cd, PyObject *key)
-{
-    Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
-    if (i == -1 && PyErr_Occurred())
-        return NULL;
-
-    if (cd->c_type->ct_flags & CT_POINTER) {
-        if (CDataOwn_Check(cd)) {
-            if (i != 0) {
-                PyErr_Format(PyExc_IndexError,
-                             "cdata '%s' can only be indexed by 0",
-                             cd->c_type->ct_name);
-                return NULL;
-            }
-        }
-        else {
-            if (cd->c_data == NULL) {
-                PyErr_Format(PyExc_RuntimeError,
-                             "cannot dereference null pointer from cdata '%s'",
-                             cd->c_type->ct_name);
-                return NULL;
-            }
-        }
-    }
-    else if (cd->c_type->ct_flags & CT_ARRAY) {
-        if (i < 0) {
-            PyErr_SetString(PyExc_IndexError,
-                            "negative index");
-            return NULL;
-        }
-        if (i >= get_array_length(cd)) {
-            PyErr_Format(PyExc_IndexError,
-                         "index too large for cdata '%s' (expected %zd < %zd)",
-                         cd->c_type->ct_name,
-                         i, get_array_length(cd));
-            return NULL;
-        }
-    }
-    else {
-        PyErr_Format(PyExc_TypeError, "cdata of type '%s' cannot be indexed",
-                     cd->c_type->ct_name);
-        return NULL;
-    }
-    return cd->c_data + i * cd->c_type->ct_itemdescr->ct_size;
-}
-
-static PyObject *
-new_array_type(CTypeDescrObject *ctptr, Py_ssize_t length);   /* forward */
-
-static CTypeDescrObject *
-_cdata_getslicearg(CDataObject *cd, PySliceObject *slice, Py_ssize_t bounds[])
-{
-    Py_ssize_t start, stop;
-    CTypeDescrObject *ct;
-
-    start = PyInt_AsSsize_t(slice->start);
-    if (start == -1 && PyErr_Occurred()) {
-        if (slice->start == Py_None)
-            PyErr_SetString(PyExc_IndexError, "slice start must be specified");
-        return NULL;
-    }
-    stop = PyInt_AsSsize_t(slice->stop);
-    if (stop == -1 && PyErr_Occurred()) {
-        if (slice->stop == Py_None)
-            PyErr_SetString(PyExc_IndexError, "slice stop must be specified");
-        return NULL;
-    }
-    if (slice->step != Py_None) {
-        PyErr_SetString(PyExc_IndexError, "slice with step not supported");
-        return NULL;
-    }
-    if (start > stop) {
-        PyErr_SetString(PyExc_IndexError, "slice start > stop");
-        return NULL;
-    }
-
-    ct = cd->c_type;
-    if (ct->ct_flags & CT_ARRAY) {
-        if (start < 0) {
-            PyErr_SetString(PyExc_IndexError,
-                            "negative index");
-            return NULL;
-        }
-        if (stop > get_array_length(cd)) {
-            PyErr_Format(PyExc_IndexError,
-                         "index too large (expected %zd <= %zd)",
-                         stop, get_array_length(cd));
-            return NULL;
-        }
-        ct = (CTypeDescrObject *)ct->ct_stuff;
-    }
-    else if (!(ct->ct_flags & CT_POINTER)) {
-        PyErr_Format(PyExc_TypeError, "cdata of type '%s' cannot be indexed",
-                     ct->ct_name);
-        return NULL;
-    }
-
-    bounds[0] = start;
-    bounds[1] = stop - start;
-    return ct;
-}
-
-static PyObject *
-cdata_slice(CDataObject *cd, PySliceObject *slice)
-{
-    char *cdata;
-    Py_ssize_t bounds[2];
-    CTypeDescrObject *ct = _cdata_getslicearg(cd, slice, bounds);
-    if (ct == NULL)
-        return NULL;
-
-    if (ct->ct_stuff == NULL) {
-        ct->ct_stuff = new_array_type(ct, -1);
-        if (ct->ct_stuff == NULL)
-            return NULL;
-    }
-    ct = (CTypeDescrObject *)ct->ct_stuff;
-
-    cdata = cd->c_data + ct->ct_itemdescr->ct_size * bounds[0];
-    return new_sized_cdata(cdata, ct, bounds[1]);
-}
-
-static int
-cdata_ass_slice(CDataObject *cd, PySliceObject *slice, PyObject *v)
-{
-    Py_ssize_t bounds[2], i, length, itemsize;
-    PyObject *it, *item;
-    PyObject *(*iternext)(PyObject *);
-    char *cdata;
-    int err;
-    CTypeDescrObject *ct = _cdata_getslicearg(cd, slice, bounds);
-    if (ct == NULL)
-        return -1;
-    ct = ct->ct_itemdescr;
-    itemsize = ct->ct_size;
-    cdata = cd->c_data + itemsize * bounds[0];
-    length = bounds[1];
-
-    if (CData_Check(v)) {
-        CTypeDescrObject *ctv = ((CDataObject *)v)->c_type;
-        if ((ctv->ct_flags & CT_ARRAY) && (ctv->ct_itemdescr == ct) &&
-            (get_array_length((CDataObject *)v) == length)) {
-            /* fast path: copying from exactly the correct type */
-            memmove(cdata, ((CDataObject *)v)->c_data, itemsize * length);
-            return 0;
-        }
-    }
-
-    /* A fast path for <char[]>[0:N] = b"somestring" or bytearray, which
-       also adds support for Python 3: otherwise, you get integers while
-       enumerating the string, and you can't set them to characters :-/
-    */
-    if ((ct->ct_flags & CT_PRIMITIVE_CHAR) && itemsize == sizeof(char)) {
-        char *src;
-        Py_ssize_t srclen;
-        if (PyBytes_Check(v)) {
-            srclen = PyBytes_GET_SIZE(v);
-            src = PyBytes_AS_STRING(v);
-        }
-        else if (PyByteArray_Check(v)) {
-            srclen = PyByteArray_GET_SIZE(v);
-            src = PyByteArray_AS_STRING(v);
-        }
-        else
-            goto other_types;
-
-        if (srclen != length) {
-            PyErr_Format(PyExc_ValueError,
-                         "need a string of length %zd, got %zd",
-                         length, srclen);
-            return -1;
-        }
-        memcpy(cdata, src, length);
-        return 0;
-    }
-   other_types:
-
-    it = PyObject_GetIter(v);
-    if (it == NULL)
-        return -1;
-    iternext = *it->ob_type->tp_iternext;
-
-    for (i = 0; i < length; i++) {
-        item = iternext(it);
-        if (item == NULL) {
-            if (!PyErr_Occurred())
-                PyErr_Format(PyExc_ValueError,
-                             "need %zd values to unpack, got %zd",
-                             length, i);
-            goto error;
-        }
-        err = convert_from_object(cdata, ct, item);
-        Py_DECREF(item);
-        if (err < 0)
-            goto error;
-
-        cdata += itemsize;
-    }
-    item = iternext(it);
-    if (item != NULL) {
-        Py_DECREF(item);
-        PyErr_Format(PyExc_ValueError,
-                     "got more than %zd values to unpack", length);
-    }
- error:
-    Py_DECREF(it);
-    return PyErr_Occurred() ? -1 : 0;
-}
-
-static PyObject *
-cdataowning_subscript(CDataObject *cd, PyObject *key)
-{
-    char *c;
-    if (PySlice_Check(key))
-        return cdata_slice(cd, (PySliceObject *)key);
-
-    c = _cdata_get_indexed_ptr(cd, key);
-    /* use 'mp_subscript' instead of 'sq_item' because we don't want
-       negative indexes to be corrected automatically */
-    if (c == NULL && PyErr_Occurred())
-        return NULL;
-
-    if (cd->c_type->ct_flags & CT_IS_PTR_TO_OWNED) {
-        PyObject *res = ((CDataObject_own_structptr *)cd)->structobj;
-        Py_INCREF(res);
-        return res;
-    }
-    else {
-        return convert_to_object(c, cd->c_type->ct_itemdescr);
-    }
-}
-
-static PyObject *
-cdata_subscript(CDataObject *cd, PyObject *key)
-{
-    char *c;
-    if (PySlice_Check(key))
-        return cdata_slice(cd, (PySliceObject *)key);
-
-    c = _cdata_get_indexed_ptr(cd, key);
-    /* use 'mp_subscript' instead of 'sq_item' because we don't want
-       negative indexes to be corrected automatically */
-    if (c == NULL && PyErr_Occurred())
-        return NULL;
-    return convert_to_object(c, cd->c_type->ct_itemdescr);
-}
-
-static int
-cdata_ass_sub(CDataObject *cd, PyObject *key, PyObject *v)
-{
-    char *c;
-    CTypeDescrObject *ctitem;
-    if (PySlice_Check(key))
-        return cdata_ass_slice(cd, (PySliceObject *)key, v);
-
-    c = _cdata_get_indexed_ptr(cd, key);
-    ctitem = cd->c_type->ct_itemdescr;
-    /* use 'mp_ass_subscript' instead of 'sq_ass_item' because we don't want
-       negative indexes to be corrected automatically */
-    if (c == NULL && PyErr_Occurred())
-        return -1;
-    if (v == NULL) {
-        PyErr_SetString(PyExc_TypeError,
-                        "'del x[n]' not supported for cdata objects");
-        return -1;
-    }
-    return convert_from_object(c, ctitem, v);
-}
-
-static PyObject *
-_cdata_add_or_sub(PyObject *v, PyObject *w, int sign)
-{
-    Py_ssize_t i, itemsize;
-    CDataObject *cd;
-    CTypeDescrObject *ctptr;
-
-    if (!CData_Check(v)) {
-        PyObject *swap;
-        assert(CData_Check(w));
-        if (sign != 1)
-            goto not_implemented;
-        swap = v;
-        v = w;
-        w = swap;
-    }
-
-    i = PyNumber_AsSsize_t(w, PyExc_OverflowError);
-    if (i == -1 && PyErr_Occurred())
-        return NULL;
-    i *= sign;
-
-    cd = (CDataObject *)v;
-    if (cd->c_type->ct_flags & CT_POINTER)
-        ctptr = cd->c_type;
-    else if (cd->c_type->ct_flags & CT_ARRAY) {
-        ctptr = (CTypeDescrObject *)cd->c_type->ct_stuff;
-    }
-    else {
-        PyErr_Format(PyExc_TypeError, "cannot add a cdata '%s' and a number",
-                     cd->c_type->ct_name);
-        return NULL;
-    }
-    itemsize = ctptr->ct_itemdescr->ct_size;
-    if (itemsize < 0) {
-        if (ctptr->ct_flags & CT_IS_VOID_PTR) {
-            itemsize = 1;
-        }
-        else {
-            PyErr_Format(PyExc_TypeError,
-                         "ctype '%s' points to items of unknown size",
-                         cd->c_type->ct_name);
-            return NULL;
-        }
-    }
-    return new_simple_cdata(cd->c_data + i * itemsize, ctptr);
-
- not_implemented:
-    Py_INCREF(Py_NotImplemented);
-    return Py_NotImplemented;
-}
-
-static PyObject *
-cdata_add(PyObject *v, PyObject *w)
-{
-    return _cdata_add_or_sub(v, w, +1);
-}
-
-static PyObject *
-cdata_sub(PyObject *v, PyObject *w)
-{
-    if (CData_Check(v) && CData_Check(w)) {
-        CDataObject *cdv = (CDataObject *)v;
-        CDataObject *cdw = (CDataObject *)w;
-        CTypeDescrObject *ct = cdw->c_type;
-        Py_ssize_t diff, itemsize;
-
-        if (ct->ct_flags & CT_ARRAY)     /* ptr_to_T - array_of_T: ok */
-            ct = (CTypeDescrObject *)ct->ct_stuff;
-
-        if (ct != cdv->c_type || !(ct->ct_flags & CT_POINTER) ||
-                (ct->ct_itemdescr->ct_size <= 0 &&
-                 !(ct->ct_flags & CT_IS_VOID_PTR))) {
-            PyErr_Format(PyExc_TypeError,
-                         "cannot subtract cdata '%s' and cdata '%s'",
-                         cdv->c_type->ct_name, ct->ct_name);
-            return NULL;
-        }
-        itemsize = ct->ct_itemdescr->ct_size;
-        diff = cdv->c_data - cdw->c_data;
-        if (itemsize > 1) {
-            if (diff % itemsize) {
-                PyErr_SetString(PyExc_ValueError,
-                     "pointer subtraction: the distance between the two "
-                     "pointers is not a multiple of the item size");
-                return NULL;
-            }
-            diff = diff / itemsize;
-        }
-#if PY_MAJOR_VERSION < 3
-        return PyInt_FromSsize_t(diff);
-#else
-        return PyLong_FromSsize_t(diff);
-#endif
-    }
-
-    return _cdata_add_or_sub(v, w, -1);
-}
-
-static void
-_cdata_attr_errmsg(char *errmsg, CDataObject *cd, PyObject *attr)
-{
-    const char *text;
-    if (!PyErr_ExceptionMatches(PyExc_AttributeError))
-        return;
-    PyErr_Clear();
-    text = PyText_AsUTF8(attr);
-    if (text == NULL)
-        return;
-    PyErr_Format(PyExc_AttributeError, errmsg, cd->c_type->ct_name, text);
-}
-
-static PyObject *
-cdata_getattro(CDataObject *cd, PyObject *attr)
-{
-    CFieldObject *cf;
-    CTypeDescrObject *ct = cd->c_type;
-    char *errmsg = "cdata '%s' has no attribute '%s'";
-    PyObject *x;
-
-    if (ct->ct_flags & CT_POINTER)
-        ct = ct->ct_itemdescr;
-
-    if (ct->ct_flags & (CT_STRUCT|CT_UNION)) {
-        switch (force_lazy_struct(ct)) {
-        case 1:
-            cf = (CFieldObject *)PyDict_GetItem(ct->ct_stuff, attr);
-            if (cf != NULL) {
-                /* read the field 'cf' */
-                char *data = cd->c_data + cf->cf_offset;
-                Py_ssize_t array_len, size;
-
-                if (cf->cf_bitshift == BS_REGULAR) {
-                    return convert_to_object(data, cf->cf_type);
-                }
-                else if (cf->cf_bitshift != BS_EMPTY_ARRAY) {
-                    return convert_to_object_bitfield(data, cf);
-                }
-
-                /* variable-length array: */
-                /* if reading variable length array from variable length
-                   struct, calculate array type from allocated length */
-                size = _cdata_var_byte_size(cd) - cf->cf_offset;
-                if (size >= 0) {
-                    array_len = size / cf->cf_type->ct_itemdescr->ct_size;
-                    return new_sized_cdata(data, cf->cf_type, array_len);
-                }
-                return new_simple_cdata(data,
-                    (CTypeDescrObject *)cf->cf_type->ct_stuff);
-            }
-            errmsg = "cdata '%s' has no field '%s'";
-            break;
-        case -1:
-            return NULL;
-        default:
-            errmsg = "cdata '%s' points to an opaque type: cannot read fields";
-            break;
-        }
-    }
-    x = PyObject_GenericGetAttr((PyObject *)cd, attr);
-    if (x == NULL)
-        _cdata_attr_errmsg(errmsg, cd, attr);
-    return x;
-}
-
-static int
-cdata_setattro(CDataObject *cd, PyObject *attr, PyObject *value)
-{
-    CFieldObject *cf;
-    CTypeDescrObject *ct = cd->c_type;
-    char *errmsg = "cdata '%s' has no attribute '%s'";
-    int x;
-
-    if (ct->ct_flags & CT_POINTER)
-        ct = ct->ct_itemdescr;
-
-    if (ct->ct_flags & (CT_STRUCT|CT_UNION)) {
-        switch (force_lazy_struct(ct)) {
-        case 1:
-            cf = (CFieldObject *)PyDict_GetItem(ct->ct_stuff, attr);
-            if (cf != NULL) {
-                /* write the field 'cf' */
-                if (value != NULL) {
-                    return convert_field_from_object(cd->c_data, cf, value);
-                }
-                else {
-                    PyErr_SetString(PyExc_AttributeError,
-                                    "cannot delete struct field");
-                    return -1;
-                }
-            }
-            errmsg = "cdata '%s' has no field '%s'";
-            break;
-        case -1:
-            return -1;
-        default:
-            errmsg = "cdata '%s' points to an opaque type: cannot write fields";
-            break;
-        }
-    }
-    x = PyObject_GenericSetAttr((PyObject *)cd, attr, value);
-    if (x < 0)
-        _cdata_attr_errmsg(errmsg, cd, attr);
-    return x;
-}
-
-static PyObject *
-convert_struct_to_owning_object(char *data, CTypeDescrObject *ct); /*forward*/
-
-static cif_description_t *
-fb_prepare_cif(PyObject *fargs, CTypeDescrObject *, Py_ssize_t, ffi_abi);
-                                                                   /*forward*/
-
-static PyObject *new_primitive_type(const char *name);             /*forward*/
-
-static CTypeDescrObject *_get_ct_int(void)
-{
-    static CTypeDescrObject *ct_int = NULL;
-    if (ct_int == NULL) {
-        ct_int = (CTypeDescrObject *)new_primitive_type("int");
-    }
-    return ct_int;
-}
-
-static Py_ssize_t
-_prepare_pointer_call_argument(CTypeDescrObject *ctptr, PyObject *init,
-                               char **output_data)
-{
-    /* 'ctptr' is here a pointer type 'ITEM *'.  Accept as argument an
-       initializer for an array 'ITEM[]'.  This includes the case of
-       passing a Python byte string to a 'char *' argument.
-
-       This function returns -1 if an error occurred,
-       0 if conversion succeeded (into *output_data),
-       or N > 0 if conversion would require N bytes of storage.
-    */
-    Py_ssize_t length, datasize;
-    CTypeDescrObject *ctitem;
-
-    if (CData_Check(init))
-        goto convert_default;
-
-    ctitem = ctptr->ct_itemdescr;
-    /* XXX some code duplication, how to avoid it? */
-    if (PyBytes_Check(init)) {
-        /* from a string: just returning the string here is fine.
-           We assume that the C code won't modify the 'char *' data. */
-        if ((ctptr->ct_flags & CT_IS_VOIDCHAR_PTR) ||
-            ((ctitem->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED))
-             && (ctitem->ct_size == sizeof(char)))) {
-#if defined(CFFI_MEM_DEBUG) || defined(CFFI_MEM_LEAK)
-            length = PyBytes_GET_SIZE(init) + 1;
-#else
-            *output_data = PyBytes_AS_STRING(init);
-            if (ctitem->ct_flags & CT_IS_BOOL)
-                if (must_be_array_of_zero_or_one(*output_data,
-                                                 PyBytes_GET_SIZE(init)) < 0)
-                    return -1;
-            return 0;
-#endif
-        }
-        else
-            goto convert_default;
-    }
-    else if (PyList_Check(init) || PyTuple_Check(init)) {
-        length = PySequence_Fast_GET_SIZE(init);
-    }
-    else if (PyUnicode_Check(init)) {
-        /* from a unicode, we add the null terminator */
-        if (ctitem->ct_size == 2)
-            length = _my_PyUnicode_SizeAsChar16(init);
-        else
-            length = _my_PyUnicode_SizeAsChar32(init);
-        length += 1;
-    }
-    else if ((ctitem->ct_flags & CT_IS_FILE) && PyFile_Check(init)) {
-        *output_data = (char *)PyFile_AsFile(init);
-        if (*output_data == NULL && PyErr_Occurred())
-            return -1;
-        return 0;
-    }
-    else {
-        /* refuse to receive just an integer (and interpret it
-           as the array size) */
-        goto convert_default;
-    }
-
-    if (ctitem->ct_size <= 0)
-        goto convert_default;
-    datasize = MUL_WRAPAROUND(length, ctitem->ct_size);
-    if ((datasize / ctitem->ct_size) != length) {
-        PyErr_SetString(PyExc_OverflowError,
-                        "array size would overflow a Py_ssize_t");
-        return -1;
-    }
-    if (datasize <= 0)
-        datasize = 1;
-    return datasize;
-
- convert_default:
-    return convert_from_object((char *)output_data, ctptr, init);
-}
-
-static PyObject*
-cdata_call(CDataObject *cd, PyObject *args, PyObject *kwds)
-{
-    char *buffer;
-    void** buffer_array;
-    cif_description_t *cif_descr;
-    Py_ssize_t i, nargs, nargs_declared;
-    PyObject *signature, *res = NULL, *fvarargs;
-    CTypeDescrObject *fresult;
-    char *resultdata;
-    char *errormsg;
-    struct freeme_s {
-        struct freeme_s *next;
-        union_alignment alignment;
-    } *freeme = NULL;
-
-    if (!(cd->c_type->ct_flags & CT_FUNCTIONPTR)) {
-        PyErr_Format(PyExc_TypeError, "cdata '%s' is not callable",
-                     cd->c_type->ct_name);
-        return NULL;
-    }
-    if (cd->c_data == NULL) {
-        PyErr_Format(PyExc_RuntimeError,
-                     "cannot call null pointer pointer from cdata '%s'",
-                     cd->c_type->ct_name);
-        return NULL;
-    }
-    if (kwds != NULL && PyDict_Size(kwds) != 0) {
-        PyErr_SetString(PyExc_TypeError,
-                "a cdata function cannot be called with keyword arguments");
-        return NULL;
-    }
-    signature = cd->c_type->ct_stuff;
-    nargs = PyTuple_Size(args);
-    if (nargs < 0)
-        return NULL;
-    nargs_declared = PyTuple_GET_SIZE(signature) - 2;
-    fresult = (CTypeDescrObject *)PyTuple_GET_ITEM(signature, 1);
-    fvarargs = NULL;
-    buffer = NULL;
-
-    cif_descr = (cif_description_t *)cd->c_type->ct_extra;
-
-    if (cif_descr != NULL) {
-        /* regular case: this function does not take '...' arguments */
-        if (nargs != nargs_declared) {
-            errormsg = "'%s' expects %zd arguments, got %zd";
-          bad_number_of_arguments:
-            PyErr_Format(PyExc_TypeError, errormsg,
-                         cd->c_type->ct_name, nargs_declared, nargs);
-            goto error;
-        }
-    }
-    else {
-        /* call of a variadic function */
-        ffi_abi fabi;
-        if (nargs < nargs_declared) {
-            errormsg = "'%s' expects at least %zd arguments, got %zd";
-            goto bad_number_of_arguments;
-        }
-        fvarargs = PyTuple_New(nargs);
-        if (fvarargs == NULL)
-            goto error;
-        for (i = 0; i < nargs_declared; i++) {
-            PyObject *o = PyTuple_GET_ITEM(signature, 2 + i);
-            Py_INCREF(o);
-            PyTuple_SET_ITEM(fvarargs, i, o);
-        }
-        for (i = nargs_declared; i < nargs; i++) {
-            PyObject *obj = PyTuple_GET_ITEM(args, i);
-            CTypeDescrObject *ct;
-
-            if (CData_Check(obj)) {
-                ct = ((CDataObject *)obj)->c_type;
-                if (ct->ct_flags & (CT_PRIMITIVE_CHAR | CT_PRIMITIVE_UNSIGNED |
-                                    CT_PRIMITIVE_SIGNED)) {
-                    if (ct->ct_size < (Py_ssize_t)sizeof(int)) {
-                        ct = _get_ct_int();
-                        if (ct == NULL)
-                            goto error;
-                    }
-                }
-                else if (ct->ct_flags & CT_ARRAY) {
-                    ct = (CTypeDescrObject *)ct->ct_stuff;
-                }
-                Py_INCREF(ct);
-            }
-            else {
-                PyErr_Format(PyExc_TypeError,
-                             "argument %zd passed in the variadic part "
-                             "needs to be a cdata object (got %.200s)",
-                             i + 1, Py_TYPE(obj)->tp_name);
-                goto error;
-            }
-            PyTuple_SET_ITEM(fvarargs, i, (PyObject *)ct);
-        }
-#if PY_MAJOR_VERSION < 3
-        fabi = PyInt_AS_LONG(PyTuple_GET_ITEM(signature, 0));
-#else
-        fabi = PyLong_AS_LONG(PyTuple_GET_ITEM(signature, 0));
-#endif
-        cif_descr = fb_prepare_cif(fvarargs, fresult, nargs_declared, fabi);
-        if (cif_descr == NULL)
-            goto error;
-    }
-
-    buffer = PyObject_Malloc(cif_descr->exchange_size);
-    if (buffer == NULL) {
-        PyErr_NoMemory();
-        goto error;
-    }
-
-    buffer_array = (void **)buffer;
-
-    for (i=0; i<nargs; i++) {
-        CTypeDescrObject *argtype;
-        char *data = buffer + cif_descr->exchange_offset_arg[1 + i];
-        PyObject *obj = PyTuple_GET_ITEM(args, i);
-
-        buffer_array[i] = data;
-
-        if (i < nargs_declared)
-            argtype = (CTypeDescrObject *)PyTuple_GET_ITEM(signature, 2 + i);
-        else
-            argtype = (CTypeDescrObject *)PyTuple_GET_ITEM(fvarargs, i);
-
-        if (argtype->ct_flags & CT_POINTER) {
-            char *tmpbuf;
-            Py_ssize_t datasize = _prepare_pointer_call_argument(
-                                            argtype, obj, (char **)data);
-            if (datasize == 0)
-                ;    /* successfully filled '*data' */
-            else if (datasize < 0)
-                goto error;
-            else {
-                if (datasize <= 512) {
-                    tmpbuf = alloca(datasize);
-                }
-                else {
-                    struct freeme_s *fp = (struct freeme_s *)PyObject_Malloc(
-                        offsetof(struct freeme_s, alignment) +
-                        (size_t)datasize);
-                    if (fp == NULL) {
-                        PyErr_NoMemory();
-                        goto error;
-                    }
-                    fp->next = freeme;
-                    freeme = fp;
-                    tmpbuf = (char *)&fp->alignment;
-                }
-                memset(tmpbuf, 0, datasize);
-                *(char **)data = tmpbuf;
-                if (convert_array_from_object(tmpbuf, argtype, obj) < 0)
-                    goto error;
-            }
-        }
-        else if (convert_from_object(data, argtype, obj) < 0)
-            goto error;
-    }
-
-    resultdata = buffer + cif_descr->exchange_offset_arg[0];
-    /*READ(cd->c_data, sizeof(void(*)(void)))*/
-
-    Py_BEGIN_ALLOW_THREADS
-    restore_errno();
-    ffi_call(&cif_descr->cif, (void (*)(void))(cd->c_data),
-             resultdata, buffer_array);
-    save_errno();
-    Py_END_ALLOW_THREADS
-
-    if (fresult->ct_flags & (CT_PRIMITIVE_CHAR | CT_PRIMITIVE_SIGNED |
-                             CT_PRIMITIVE_UNSIGNED)) {
-#ifdef WORDS_BIGENDIAN
-        /* For results of precisely these types, libffi has a strange
-           rule that they will be returned as a whole 'ffi_arg' if they
-           are smaller.  The difference only matters on big-endian. */
-        if (fresult->ct_size < sizeof(ffi_arg))
-            resultdata += (sizeof(ffi_arg) - fresult->ct_size);
-#endif
-        res = convert_to_object(resultdata, fresult);
-    }
-    else if (fresult->ct_flags & CT_VOID) {
-        res = Py_None;
-        Py_INCREF(res);
-    }
-    else if (fresult->ct_flags & CT_STRUCT) {
-        res = convert_struct_to_owning_object(resultdata, fresult);
-    }
-    else {
-        res = convert_to_object(resultdata, fresult);
-    }
-    /* fall-through */
-
- error:
-    while (freeme != NULL) {
-        void *p = (void *)freeme;
-        freeme = freeme->next;
-        PyObject_Free(p);
-    }
-    if (buffer)
-        PyObject_Free(buffer);
-    if (fvarargs != NULL) {
-        Py_DECREF(fvarargs);
-        if (cif_descr != NULL)  /* but only if fvarargs != NULL, if variadic */
-            PyObject_Free(cif_descr);
-    }
-    return res;
-}
-
-static PyObject *cdata_dir(PyObject *cd, PyObject *noarg)
-{
-    CTypeDescrObject *ct = ((CDataObject *)cd)->c_type;
-
-    /* replace the type 'pointer-to-t' with just 't' */
-    if (ct->ct_flags & CT_POINTER) {
-        ct = ct->ct_itemdescr;
-    }
-    if ((ct->ct_flags & (CT_STRUCT | CT_UNION)) &&
-        !(ct->ct_flags & CT_IS_OPAQUE)) {
-
-        /* for non-opaque structs or unions */
-        if (force_lazy_struct(ct) < 0)
-            return NULL;
-        return PyDict_Keys(ct->ct_stuff);
-    }
-    else {
-        return PyList_New(0);   /* empty list for the other cases */
-    }
-}
-
-static PyObject *cdata_complex(PyObject *cd_, PyObject *noarg)
-{
-    CDataObject *cd = (CDataObject *)cd_;
-
-    if (cd->c_type->ct_flags & CT_PRIMITIVE_COMPLEX) {
-        Py_complex value = read_raw_complex_data(cd->c_data, cd->c_type->ct_size);
-        PyObject *op = PyComplex_FromCComplex(value);
-        return op;
-    }
-    /* <cdata 'float'> or <cdata 'int'> cannot be directly converted by
-       calling complex(), just like <cdata 'int'> cannot be directly
-       converted by calling float() */
-
-    PyErr_Format(PyExc_TypeError, "complex() not supported on cdata '%s'",
-                 cd->c_type->ct_name);
-    return NULL;
-}
-
-static int explicit_release_case(PyObject *cd)
-{
-    CTypeDescrObject *ct = ((CDataObject *)cd)->c_type;
-    if (Py_TYPE(cd) == &CDataOwning_Type) {
-        if ((ct->ct_flags & (CT_POINTER | CT_ARRAY)) != 0)   /* ffi.new() */
-            return 0;
-    }
-    else if (Py_TYPE(cd) == &CDataFromBuf_Type) {
-        return 1;    /* ffi.from_buffer() */
-    }
-    else if (Py_TYPE(cd) == &CDataGCP_Type) {
-        return 2;    /* ffi.gc() */
-    }
-    PyErr_SetString(PyExc_ValueError,
-        "only 'cdata' object from ffi.new(), ffi.gc(), ffi.from_buffer() "
-        "or ffi.new_allocator()() can be used with the 'with' keyword or "
-        "ffi.release()");
-    return -1;
-}
-
-static PyObject *cdata_enter(PyObject *cd, PyObject *noarg)
-{
-    if (explicit_release_case(cd) < 0)   /* only to check the ctype */
-        return NULL;
-    Py_INCREF(cd);
-    return cd;
-}
-
-static PyObject *cdata_exit(PyObject *cd, PyObject *args)
-{
-    /* 'args' ignored */
-    CTypeDescrObject *ct;
-    Py_buffer *view;
-    switch (explicit_release_case(cd))
-    {
-        case 0:    /* ffi.new() */
-            /* no effect on CPython: raw memory is allocated with the
-               same malloc() as the object itself, so it can't be
-               released independently.  If we use a custom allocator,
-               then it's implemented with ffi.gc(). */
-            ct = ((CDataObject *)cd)->c_type;
-            if (ct->ct_flags & CT_IS_PTR_TO_OWNED) {
-                PyObject *x = ((CDataObject_own_structptr *)cd)->structobj;
-                if (Py_TYPE(x) == &CDataGCP_Type) {
-                    /* this is a special case for
-                       ffi.new_allocator()("struct-or-union *") */
-                    cdatagcp_finalize((CDataObject_gcp *)x);
-                }
-            }
-            break;
-
-        case 1:    /* ffi.from_buffer() */
-            view = ((CDataObject_frombuf *)cd)->bufferview;
-            PyBuffer_Release(view);
-            break;
-
-        case 2:    /* ffi.gc() or ffi.new_allocator()("not-struct-nor-union") */
-            /* call the destructor immediately */
-            cdatagcp_finalize((CDataObject_gcp *)cd);
-            break;
-
-        default:
-            return NULL;
-    }
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *cdata_iter(CDataObject *);
-
-static PyNumberMethods CData_as_number = {
-    (binaryfunc)cdata_add,      /*nb_add*/
-    (binaryfunc)cdata_sub,      /*nb_subtract*/
-    0,                          /*nb_multiply*/
-#if PY_MAJOR_VERSION < 3
-    0,                          /*nb_divide*/
-#endif
-    0,                          /*nb_remainder*/
-    0,                          /*nb_divmod*/
-    0,                          /*nb_power*/
-    0,                          /*nb_negative*/
-    0,                          /*nb_positive*/
-    0,                          /*nb_absolute*/
-    (inquiry)cdata_nonzero,     /*nb_nonzero*/
-    0,                          /*nb_invert*/
-    0,                          /*nb_lshift*/
-    0,                          /*nb_rshift*/
-    0,                          /*nb_and*/
-    0,                          /*nb_xor*/
-    0,                          /*nb_or*/
-#if PY_MAJOR_VERSION < 3
-    0,                          /*nb_coerce*/
-#endif
-    (unaryfunc)cdata_int,       /*nb_int*/
-#if PY_MAJOR_VERSION < 3
-    (unaryfunc)cdata_long,      /*nb_long*/
-#else
-    0,
-#endif
-    (unaryfunc)cdata_float,     /*nb_float*/
-    0,                          /*nb_oct*/
-    0,                          /*nb_hex*/
-};
-
-static PyMappingMethods CData_as_mapping = {
-    (lenfunc)cdata_length, /*mp_length*/
-    (binaryfunc)cdata_subscript, /*mp_subscript*/
-    (objobjargproc)cdata_ass_sub, /*mp_ass_subscript*/
-};
-
-static PyMappingMethods CDataOwn_as_mapping = {
-    (lenfunc)cdata_length, /*mp_length*/
-    (binaryfunc)cdataowning_subscript, /*mp_subscript*/
-    (objobjargproc)cdata_ass_sub, /*mp_ass_subscript*/
-};
-
-static PyMethodDef cdata_methods[] = {
-    {"__dir__",     cdata_dir,      METH_NOARGS},
-    {"__complex__", cdata_complex,  METH_NOARGS},
-    {"__enter__",   cdata_enter,    METH_NOARGS},
-    {"__exit__",    cdata_exit,     METH_VARARGS},
-    {NULL,          NULL}           /* sentinel */
-};
-
-static PyTypeObject CData_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend._CDataBase",
-    sizeof(CDataObject),
-    0,
-    (destructor)cdata_dealloc,                  /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_compare */
-    (reprfunc)cdata_repr,                       /* tp_repr */
-    &CData_as_number,                           /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    &CData_as_mapping,                          /* tp_as_mapping */
-    cdata_hash,                                 /* tp_hash */
-    (ternaryfunc)cdata_call,                    /* tp_call */
-    0,                                          /* tp_str */
-    (getattrofunc)cdata_getattro,               /* tp_getattro */
-    (setattrofunc)cdata_setattro,               /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
-    "The internal base type for CData objects.  Use FFI.CData to access "
-    "it.  Always check with isinstance(): subtypes are sometimes returned "
-    "on CPython, for performance reasons.",     /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    cdata_richcompare,                          /* tp_richcompare */
-    offsetof(CDataObject, c_weakreflist),       /* tp_weaklistoffset */
-    (getiterfunc)cdata_iter,                    /* tp_iter */
-    0,                                          /* tp_iternext */
-    cdata_methods,                              /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    PyObject_Del,                               /* tp_free */
-};
-
-static PyTypeObject CDataOwning_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.__CDataOwn",
-    sizeof(CDataObject),
-    0,
-    (destructor)cdataowning_dealloc,            /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_compare */
-    (reprfunc)cdataowning_repr,                 /* tp_repr */
-    0,  /* inherited */                         /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    &CDataOwn_as_mapping,                       /* tp_as_mapping */
-    0,  /* inherited */                         /* tp_hash */
-    0,  /* inherited */                         /* tp_call */
-    0,                                          /* tp_str */
-    0,  /* inherited */                         /* tp_getattro */
-    0,  /* inherited */                         /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
-    "This is an internal subtype of _CDataBase for performance only on "
-    "CPython.  Check with isinstance(x, ffi.CData).",   /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,  /* inherited */                         /* tp_richcompare */
-    0,  /* inherited */                         /* tp_weaklistoffset */
-    0,  /* inherited */                         /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,  /* inherited */                         /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    &CData_Type,                                /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    free,                                       /* tp_free */
-};
-
-static PyTypeObject CDataOwningGC_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.__CDataOwnGC",
-    sizeof(CDataObject_own_structptr),
-    0,
-    (destructor)cdataowninggc_dealloc,          /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_compare */
-    (reprfunc)cdataowninggc_repr,               /* tp_repr */
-    0,  /* inherited */                         /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,  /* inherited */                         /* tp_as_mapping */
-    0,  /* inherited */                         /* tp_hash */
-    0,  /* inherited */                         /* tp_call */
-    0,                                          /* tp_str */
-    0,  /* inherited */                         /* tp_getattro */
-    0,  /* inherited */                         /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES  /* tp_flags */
-                       | Py_TPFLAGS_HAVE_GC,
-    "This is an internal subtype of _CDataBase for performance only on "
-    "CPython.  Check with isinstance(x, ffi.CData).",   /* tp_doc */
-    (traverseproc)cdataowninggc_traverse,       /* tp_traverse */
-    (inquiry)cdataowninggc_clear,               /* tp_clear */
-    0,  /* inherited */                         /* tp_richcompare */
-    0,  /* inherited */                         /* tp_weaklistoffset */
-    0,  /* inherited */                         /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,  /* inherited */                         /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    &CDataOwning_Type,                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    PyObject_GC_Del,                            /* tp_free */
-};
-
-static PyTypeObject CDataFromBuf_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.__CDataFromBuf",
-    sizeof(CDataObject_frombuf),
-    0,
-    (destructor)cdatafrombuf_dealloc,           /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_compare */
-    (reprfunc)cdatafrombuf_repr,                /* tp_repr */
-    0,  /* inherited */                         /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,  /* inherited */                         /* tp_as_mapping */
-    0,  /* inherited */                         /* tp_hash */
-    0,  /* inherited */                         /* tp_call */
-    0,                                          /* tp_str */
-    0,  /* inherited */                         /* tp_getattro */
-    0,  /* inherited */                         /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES  /* tp_flags */
-                       | Py_TPFLAGS_HAVE_GC,
-    "This is an internal subtype of _CDataBase for performance only on "
-    "CPython.  Check with isinstance(x, ffi.CData).",   /* tp_doc */
-    (traverseproc)cdatafrombuf_traverse,        /* tp_traverse */
-    (inquiry)cdatafrombuf_clear,                /* tp_clear */
-    0,  /* inherited */                         /* tp_richcompare */
-    0,  /* inherited */                         /* tp_weaklistoffset */
-    0,  /* inherited */                         /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,  /* inherited */                         /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    &CData_Type,                                /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    PyObject_GC_Del,                            /* tp_free */
-};
-
-static PyTypeObject CDataGCP_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.__CDataGCP",
-    sizeof(CDataObject_gcp),
-    0,
-    (destructor)cdatagcp_dealloc,               /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_compare */
-    0,  /* inherited */                         /* tp_repr */
-    0,  /* inherited */                         /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,  /* inherited */                         /* tp_as_mapping */
-    0,  /* inherited */                         /* tp_hash */
-    0,  /* inherited */                         /* tp_call */
-    0,                                          /* tp_str */
-    0,  /* inherited */                         /* tp_getattro */
-    0,  /* inherited */                         /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES  /* tp_flags */
-#ifdef Py_TPFLAGS_HAVE_FINALIZE
-                       | Py_TPFLAGS_HAVE_FINALIZE
-#endif
-                       | Py_TPFLAGS_HAVE_GC,
-    "This is an internal subtype of _CDataBase for performance only on "
-    "CPython.  Check with isinstance(x, ffi.CData).",   /* tp_doc */
-    (traverseproc)cdatagcp_traverse,            /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,  /* inherited */                         /* tp_richcompare */
-    0,  /* inherited */                         /* tp_weaklistoffset */
-    0,  /* inherited */                         /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,  /* inherited */                         /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    &CData_Type,                                /* tp_base */
-#ifdef Py_TPFLAGS_HAVE_FINALIZE  /* CPython >= 3.4 */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,  /* inherited */                         /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* version_tag */
-    (destructor)cdatagcp_finalize,              /* tp_finalize */
-#endif
-};
-
-/************************************************************/
-
-typedef struct {
-    PyObject_HEAD
-    char *di_next, *di_stop;
-    CDataObject *di_object;
-    CTypeDescrObject *di_itemtype;
-} CDataIterObject;
-
-static PyObject *
-cdataiter_next(CDataIterObject *it)
-{
-    char *result = it->di_next;
-    if (result != it->di_stop) {
-        it->di_next = result + it->di_itemtype->ct_size;
-        return convert_to_object(result, it->di_itemtype);
-    }
-    return NULL;
-}
-
-static void
-cdataiter_dealloc(CDataIterObject *it)
-{
-    Py_DECREF(it->di_object);
-    PyObject_Del(it);
-}
-
-static PyTypeObject CDataIter_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.__CData_iterator",       /* tp_name */
-    sizeof(CDataIterObject),                /* tp_basicsize */
-    0,                                      /* tp_itemsize */
-    /* methods */
-    (destructor)cdataiter_dealloc,          /* tp_dealloc */
-    0,                                      /* tp_print */
-    0,                                      /* tp_getattr */
-    0,                                      /* tp_setattr */
-    0,                                      /* tp_compare */
-    0,                                      /* tp_repr */
-    0,                                      /* tp_as_number */
-    0,                                      /* tp_as_sequence */
-    0,                                      /* tp_as_mapping */
-    0,                                      /* tp_hash */
-    0,                                      /* tp_call */
-    0,                                      /* tp_str */
-    PyObject_GenericGetAttr,                /* tp_getattro */
-    0,                                      /* tp_setattro */
-    0,                                      /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                     /* tp_flags */
-    0,                                      /* tp_doc */
-    0,                                      /* tp_traverse */
-    0,                                      /* tp_clear */
-    0,                                      /* tp_richcompare */
-    0,                                      /* tp_weaklistoffset */
-    PyObject_SelfIter,                      /* tp_iter */
-    (iternextfunc)cdataiter_next,           /* tp_iternext */
-};
-
-static PyObject *
-cdata_iter(CDataObject *cd)
-{
-    CDataIterObject *it;
-
-    if (!(cd->c_type->ct_flags & CT_ARRAY)) {
-        PyErr_Format(PyExc_TypeError, "cdata '%s' does not support iteration",
-                     cd->c_type->ct_name);
-        return NULL;
-    }
-
-    it = PyObject_New(CDataIterObject, &CDataIter_Type);
-    if (it == NULL)
-        return NULL;
-
-    Py_INCREF(cd);
-    it->di_object = cd;
-    it->di_itemtype = cd->c_type->ct_itemdescr;
-    it->di_next = cd->c_data;
-    it->di_stop = cd->c_data + get_array_length(cd) * it->di_itemtype->ct_size;
-    return (PyObject *)it;
-}
-
-/************************************************************/
-
-static CDataObject *allocate_owning_object(Py_ssize_t size,
-                                           CTypeDescrObject *ct,
-                                           int dont_clear)
-{
-    /* note: objects with &CDataOwning_Type are always allocated with
-       either a plain malloc() or calloc(), and freed with free(). */
-    CDataObject *cd;
-    if (dont_clear)
-        cd = malloc(size);
-    else
-        cd = calloc(size, 1);
-    if (PyObject_Init((PyObject *)cd, &CDataOwning_Type) == NULL)
-        return NULL;
-
-    Py_INCREF(ct);
-    cd->c_type = ct;
-    cd->c_weakreflist = NULL;
-    return cd;
-}
-
-static PyObject *
-convert_struct_to_owning_object(char *data, CTypeDescrObject *ct)
-{
-    /* also accepts unions, for the API mode */
-    CDataObject *cd;
-    Py_ssize_t dataoffset = offsetof(CDataObject_own_nolength, alignment);
-    Py_ssize_t datasize = ct->ct_size;
-
-    if (datasize < 0) {
-        PyErr_SetString(PyExc_TypeError,
-                        "return type is an opaque structure or union");
-        return NULL;
-    }
-    if (ct->ct_flags & CT_WITH_VAR_ARRAY) {
-        PyErr_SetString(PyExc_TypeError,
-                  "return type is a struct/union with a varsize array member");
-        return NULL;
-    }
-    cd = allocate_owning_object(dataoffset + datasize, ct, /*dont_clear=*/1);
-    if (cd == NULL)
-        return NULL;
-    cd->c_data = ((char *)cd) + dataoffset;
-
-    memcpy(cd->c_data, data, datasize);
-    return (PyObject *)cd;
-}
-
-static CDataObject *allocate_gcp_object(CDataObject *origobj,
-                                        CTypeDescrObject *ct,
-                                        PyObject *destructor)
-{
-    CDataObject_gcp *cd = PyObject_GC_New(CDataObject_gcp, &CDataGCP_Type);
-    if (cd == NULL)
-        return NULL;
-
-    Py_XINCREF(destructor);
-    Py_INCREF(origobj);
-    Py_INCREF(ct);
-    cd->head.c_data = origobj->c_data;
-    cd->head.c_type = ct;
-    cd->head.c_weakreflist = NULL;
-    cd->origobj = (PyObject *)origobj;
-    cd->destructor = destructor;
-
-    PyObject_GC_Track(cd);
-    return (CDataObject *)cd;
-}
-
-static CDataObject *allocate_with_allocator(Py_ssize_t basesize,
-                                            Py_ssize_t datasize,
-                                            CTypeDescrObject *ct,
-                                            const cffi_allocator_t *allocator)
-{
-    CDataObject *cd;
-
-    if (allocator->ca_alloc == NULL) {
-        cd = allocate_owning_object(basesize + datasize, ct,
-                                    allocator->ca_dont_clear);
-        if (cd == NULL)
-            return NULL;
-        cd->c_data = ((char *)cd) + basesize;
-    }
-    else {
-        PyObject *res = PyObject_CallFunction(allocator->ca_alloc, "n", datasize);
-        if (res == NULL)
-            return NULL;
-
-        if (!CData_Check(res)) {
-            PyErr_Format(PyExc_TypeError,
-                         "alloc() must return a cdata object (got %.200s)",
-                         Py_TYPE(res)->tp_name);
-            Py_DECREF(res);
-            return NULL;
-        }
-        cd = (CDataObject *)res;
-        if (!(cd->c_type->ct_flags & (CT_POINTER|CT_ARRAY))) {
-            PyErr_Format(PyExc_TypeError,
-                         "alloc() must return a cdata pointer, not '%s'",
-                         cd->c_type->ct_name);
-            Py_DECREF(res);
-            return NULL;
-        }
-        if (!cd->c_data) {
-            PyErr_SetString(PyExc_MemoryError, "alloc() returned NULL");
-            Py_DECREF(res);
-            return NULL;
-        }
-
-        cd = allocate_gcp_object(cd, ct, allocator->ca_free);
-        Py_DECREF(res);
-        if (!allocator->ca_dont_clear)
-            memset(cd->c_data, 0, datasize);
-    }
-    return cd;
-}
-
-static PyObject *direct_newp(CTypeDescrObject *ct, PyObject *init,
-                             const cffi_allocator_t *allocator)
-{
-    CTypeDescrObject *ctitem;
-    CDataObject *cd;
-    Py_ssize_t dataoffset, datasize, explicitlength;
-
-    explicitlength = -1;
-    if (ct->ct_flags & CT_POINTER) {
-        dataoffset = offsetof(CDataObject_own_nolength, alignment);
-        ctitem = ct->ct_itemdescr;
-        datasize = ctitem->ct_size;
-        if (datasize < 0) {
-            PyErr_Format(PyExc_TypeError,
-                         "cannot instantiate ctype '%s' of unknown size",
-                         ctitem->ct_name);
-            return NULL;
-        }
-        if (ctitem->ct_flags & CT_PRIMITIVE_CHAR)
-            datasize *= 2;   /* forcefully add another character: a null */
-
-        if (ctitem->ct_flags & (CT_STRUCT | CT_UNION)) {
-            if (force_lazy_struct(ctitem) < 0)   /* for CT_WITH_VAR_ARRAY */
-                return NULL;
-
-            if (ctitem->ct_flags & CT_WITH_VAR_ARRAY) {
-                assert(ct->ct_flags & CT_IS_PTR_TO_OWNED);
-                dataoffset = offsetof(CDataObject_own_length, alignment);
-
-                if (init != Py_None) {
-                    Py_ssize_t optvarsize = datasize;
-                    if (convert_struct_from_object(NULL, ctitem, init,
-                                                   &optvarsize) < 0)
-                        return NULL;
-                    datasize = optvarsize;
-                }
-            }
-        }
-    }
-    else if (ct->ct_flags & CT_ARRAY) {
-        dataoffset = offsetof(CDataObject_own_nolength, alignment);
-        datasize = ct->ct_size;
-        if (datasize < 0) {
-            explicitlength = get_new_array_length(ct->ct_itemdescr, &init);
-            if (explicitlength < 0)
-                return NULL;
-            ctitem = ct->ct_itemdescr;
-            dataoffset = offsetof(CDataObject_own_length, alignment);
-            datasize = MUL_WRAPAROUND(explicitlength, ctitem->ct_size);
-            if (explicitlength > 0 &&
-                    (datasize / explicitlength) != ctitem->ct_size) {
-                PyErr_SetString(PyExc_OverflowError,
-                                "array size would overflow a Py_ssize_t");
-                return NULL;
-            }
-        }
-    }
-    else {
-        PyErr_Format(PyExc_TypeError,
-                     "expected a pointer or array ctype, got '%s'",
-                     ct->ct_name);
-        return NULL;
-    }
-
-    if (ct->ct_flags & CT_IS_PTR_TO_OWNED) {
-        /* common case of ptr-to-struct (or ptr-to-union): for this case
-           we build two objects instead of one, with the memory-owning
-           one being really the struct (or union) and the returned one
-           having a strong reference to it */
-        CDataObject *cds;
-
-        cds = allocate_with_allocator(dataoffset, datasize, ct->ct_itemdescr,
-                                      allocator);
-        if (cds == NULL)
-            return NULL;
-
-        cd = allocate_owning_object(sizeof(CDataObject_own_structptr), ct,
-                                    /*dont_clear=*/1);
-        if (cd == NULL) {
-            Py_DECREF(cds);
-            return NULL;
-        }
-        /* store the only reference to cds into cd */
-        ((CDataObject_own_structptr *)cd)->structobj = (PyObject *)cds;
-        /* store information about the allocated size of the struct */
-        if (dataoffset == offsetof(CDataObject_own_length, alignment)) {
-            ((CDataObject_own_length *)cds)->length = datasize;
-        }
-        assert(explicitlength < 0);
-
-        cd->c_data = cds->c_data;
-    }
-    else {
-        cd = allocate_with_allocator(dataoffset, datasize, ct, allocator);
-        if (cd == NULL)
-            return NULL;
-
-        if (explicitlength >= 0)
-            ((CDataObject_own_length*)cd)->length = explicitlength;
-    }
-
-    if (init != Py_None) {
-        if (convert_from_object(cd->c_data,
-              (ct->ct_flags & CT_POINTER) ? ct->ct_itemdescr : ct, init) < 0) {
-            Py_DECREF(cd);
-            return NULL;
-        }
-    }
-    return (PyObject *)cd;
-}
-
-static PyObject *b_newp(PyObject *self, PyObject *args)
-{
-    CTypeDescrObject *ct;
-    PyObject *init = Py_None;
-    if (!PyArg_ParseTuple(args, "O!|O:newp", &CTypeDescr_Type, &ct, &init))
-        return NULL;
-    return direct_newp(ct, init, &default_allocator);
-}
-
-static int
-_my_PyObject_AsBool(PyObject *ob)
-{
-    /* convert and cast a Python object to a boolean.  Accept an integer
-       or a float object, up to a CData 'long double'. */
-    PyObject *io;
-    PyNumberMethods *nb;
-    int res;
-
-#if PY_MAJOR_VERSION < 3
-    if (PyInt_Check(ob)) {
-        return PyInt_AS_LONG(ob) != 0;
-    }
-    else
-#endif
-    if (PyLong_Check(ob)) {
-        return _PyLong_Sign(ob) != 0;
-    }
-    else if (PyFloat_Check(ob)) {
-        return PyFloat_AS_DOUBLE(ob) != 0.0;
-    }
-    else if (CData_Check(ob)) {
-        CDataObject *cd = (CDataObject *)ob;
-        if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) {
-            /*READ(cd->c_data, cd->c_type->ct_size)*/
-            if (cd->c_type->ct_flags & CT_IS_LONGDOUBLE) {
-                /* 'long double' objects: return the answer directly */
-                return read_raw_longdouble_data(cd->c_data) != 0.0;
-            }
-            else {
-                /* 'float'/'double' objects: return the answer directly */
-                return read_raw_float_data(cd->c_data,
-                                           cd->c_type->ct_size) != 0.0;
-            }
-        }
-    }
-    nb = ob->ob_type->tp_as_number;
-    if (nb == NULL || (nb->nb_float == NULL && nb->nb_int == NULL)) {
-        PyErr_SetString(PyExc_TypeError, "integer/float expected");
-        return -1;
-    }
-    if (nb->nb_float && !CData_Check(ob))
-        io = (*nb->nb_float) (ob);
-    else
-        io = (*nb->nb_int) (ob);
-    if (io == NULL)
-        return -1;
-
-    if (PyIntOrLong_Check(io) || PyFloat_Check(io)) {
-        res = _my_PyObject_AsBool(io);
-    }
-    else {
-        PyErr_SetString(PyExc_TypeError, "integer/float conversion failed");
-        res = -1;
-    }
-    Py_DECREF(io);
-    return res;
-}
-
-static CDataObject *_new_casted_primitive(CTypeDescrObject *ct)
-{
-    int dataoffset = offsetof(CDataObject_casted_primitive, alignment);
-    CDataObject *cd = (CDataObject *)PyObject_Malloc(dataoffset + ct->ct_size);
-    if (PyObject_Init((PyObject *)cd, &CData_Type) == NULL)
-        return NULL;
-    Py_INCREF(ct);
-    cd->c_type = ct;
-    cd->c_data = ((char*)cd) + dataoffset;
-    cd->c_weakreflist = NULL;
-    return cd;
-}
-
-static CDataObject *cast_to_integer_or_char(CTypeDescrObject *ct, PyObject *ob)
-{
-    unsigned PY_LONG_LONG value;
-    CDataObject *cd;
-
-    if (CData_Check(ob) &&
-        ((CDataObject *)ob)->c_type->ct_flags &
-                                 (CT_POINTER|CT_FUNCTIONPTR|CT_ARRAY)) {
-        value = (Py_intptr_t)((CDataObject *)ob)->c_data;
-    }
-#if PY_MAJOR_VERSION < 3
-    else if (PyString_Check(ob)) {
-        if (PyString_GET_SIZE(ob) != 1) {
-            PyErr_Format(PyExc_TypeError,
-                         "cannot cast string of length %zd to ctype '%s'",
-                         PyString_GET_SIZE(ob), ct->ct_name);
-            return NULL;
-        }
-        value = (unsigned char)PyString_AS_STRING(ob)[0];
-    }
-#endif
-    else if (PyUnicode_Check(ob)) {
-        char err_buf[80];
-        cffi_char32_t ordinal;
-        if (_my_PyUnicode_AsSingleChar32(ob, &ordinal, err_buf) < 0) {
-            PyErr_Format(PyExc_TypeError,
-                         "cannot cast %s to ctype '%s'", err_buf, ct->ct_name);
-            return NULL;
-        }
-        /* the types char16_t and char32_t are both unsigned.  However,
-           wchar_t might be signed.  In theory it does not matter,
-           because 'ordinal' comes from a regular Python unicode. */
-#ifdef HAVE_WCHAR_H
-        if (ct->ct_flags & CT_IS_SIGNED_WCHAR)
-            value = (wchar_t)ordinal;
-        else
-#endif
-            value = ordinal;
-    }
-    else if (PyBytes_Check(ob)) {
-        int res = _convert_to_char(ob);
-        if (res < 0)
-            return NULL;
-        value = (unsigned char)res;
-    }
-    else if (ct->ct_flags & CT_IS_BOOL) {
-        int res = _my_PyObject_AsBool(ob);
-        if (res < 0)
-            return NULL;
-        value = res;
-    }
-    else {
-        value = _my_PyLong_AsUnsignedLongLong(ob, 0);
-        if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
-            return NULL;
-    }
-    if (ct->ct_flags & CT_IS_BOOL)
-        value = !!value;
-    cd = _new_casted_primitive(ct);
-    if (cd != NULL)
-        write_raw_integer_data(cd->c_data, value, ct->ct_size);
-    return cd;
-}
-
-/* returns -1 if cannot cast, 0 if we don't get a value, 1 if we do */
-static int check_bytes_for_float_compatible(PyObject *io, double *out_value)
-{
-    if (PyBytes_Check(io)) {
-        if (PyBytes_GET_SIZE(io) != 1)
-            goto error;
-        *out_value = (unsigned char)PyBytes_AS_STRING(io)[0];
-        return 1;
-    }
-    else if (PyUnicode_Check(io)) {
-        char ignored[80];
-        cffi_char32_t ordinal;
-        if (_my_PyUnicode_AsSingleChar32(io, &ordinal, ignored) < 0)
-            goto error;
-        /* the signness of the 32-bit version of wide chars should not
-         * matter here, because 'ordinal' comes from a normal Python
-         * unicode string */
-        *out_value = ordinal;
-        return 1;
-    }
-    *out_value = 0;   /* silence a gcc warning if this function is inlined */
-    return 0;
-
- error:
-    Py_DECREF(io);
-    *out_value = 0;   /* silence a gcc warning if this function is inlined */
-    return -1;
-}
-
-static PyObject *do_cast(CTypeDescrObject *ct, PyObject *ob)
-{
-    CDataObject *cd;
-
-    if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR|CT_ARRAY) &&
-        ct->ct_size >= 0) {
-        /* cast to a pointer, to a funcptr, or to an array.
-           Note that casting to an array is an extension to the C language,
-           which seems to be necessary in order to sanely get a
-           <cdata 'int[3]'> at some address. */
-        unsigned PY_LONG_LONG value;
-
-        if (CData_Check(ob)) {
-            CDataObject *cdsrc = (CDataObject *)ob;
-            if (cdsrc->c_type->ct_flags &
-                    (CT_POINTER|CT_FUNCTIONPTR|CT_ARRAY)) {
-                return new_simple_cdata(cdsrc->c_data, ct);
-            }
-        }
-        if ((ct->ct_flags & CT_POINTER) &&
-                (ct->ct_itemdescr->ct_flags & CT_IS_FILE) &&
-                PyFile_Check(ob)) {
-            FILE *f = PyFile_AsFile(ob);
-            if (f == NULL && PyErr_Occurred())
-                return NULL;
-            return new_simple_cdata((char *)f, ct);
-        }
-        value = _my_PyLong_AsUnsignedLongLong(ob, 0);
-        if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
-            return NULL;
-        return new_simple_cdata((char *)(Py_intptr_t)value, ct);
-    }
-    else if (ct->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED
-                             |CT_PRIMITIVE_CHAR)) {
-        /* cast to an integer type or a char */
-        return (PyObject *)cast_to_integer_or_char(ct, ob);
-    }
-    else if (ct->ct_flags & CT_PRIMITIVE_FLOAT) {
-        /* cast to a float */
-        double value;
-        PyObject *io;
-        int res;
-
-        if (CData_Check(ob)) {
-            CDataObject *cdsrc = (CDataObject *)ob;
-
-            if (!(cdsrc->c_type->ct_flags & CT_PRIMITIVE_ANY))
-                goto cannot_cast;
-            io = convert_to_object(cdsrc->c_data, cdsrc->c_type);
-            if (io == NULL)
-                return NULL;
-        }
-        else {
-            io = ob;
-            Py_INCREF(io);
-        }
-
-        res = check_bytes_for_float_compatible(io, &value);
-        if (res == -1)
-            goto cannot_cast;
-        if (res == 0) {
-            if ((ct->ct_flags & CT_IS_LONGDOUBLE) &&
-                 CData_Check(io) &&
-                 (((CDataObject *)io)->c_type->ct_flags & CT_IS_LONGDOUBLE)) {
-                long double lvalue;
-                char *data = ((CDataObject *)io)->c_data;
-                /*READ(data, sizeof(long double)*/
-                lvalue = read_raw_longdouble_data(data);
-                Py_DECREF(io);
-                cd = _new_casted_primitive(ct);
-                if (cd != NULL)
-                    write_raw_longdouble_data(cd->c_data, lvalue);
-                return (PyObject *)cd;
-            }
-            value = PyFloat_AsDouble(io);
-        }
-        Py_DECREF(io);
-        if (value == -1.0 && PyErr_Occurred())
-            return NULL;
-
-        cd = _new_casted_primitive(ct);
-        if (cd != NULL) {
-            if (!(ct->ct_flags & CT_IS_LONGDOUBLE))
-                write_raw_float_data(cd->c_data, value, ct->ct_size);
-            else
-                write_raw_longdouble_data(cd->c_data, (long double)value);
-        }
-        return (PyObject *)cd;
-    }
-    else if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) {
-        /* cast to a complex */
-        Py_complex value;
-        PyObject *io;
-        int res;
-
-        if (CData_Check(ob)) {
-            CDataObject *cdsrc = (CDataObject *)ob;
-
-            if (!(cdsrc->c_type->ct_flags & CT_PRIMITIVE_ANY))
-                goto cannot_cast;
-            io = convert_to_object(cdsrc->c_data, cdsrc->c_type);
-            if (io == NULL)
-                return NULL;
-        }
-        else {
-            io = ob;
-            Py_INCREF(io);
-        }
-
-        res = check_bytes_for_float_compatible(io, &value.real);
-        if (res == -1)
-            goto cannot_cast;
-        if (res == 1) {
-            // got it from string
-            value.imag = 0.0;
-        } else {
-            value = PyComplex_AsCComplex(io);
-        }
-        Py_DECREF(io);
-        if (PyErr_Occurred()) {
-            return NULL;
-        }
-        cd = _new_casted_primitive(ct);
-        if (cd != NULL) {
-            write_raw_complex_data(cd->c_data, value, ct->ct_size);
-        }
-        return (PyObject *)cd;
-    }
-    else {
-        PyErr_Format(PyExc_TypeError, "cannot cast to ctype '%s'",
-                     ct->ct_name);
-        return NULL;
-    }
-
- cannot_cast:
-    if (CData_Check(ob))
-        PyErr_Format(PyExc_TypeError, "cannot cast ctype '%s' to ctype '%s'",
-                     ((CDataObject *)ob)->c_type->ct_name, ct->ct_name);
-    else
-        PyErr_Format(PyExc_TypeError,
-                     "cannot cast %.200s object to ctype '%s'",
-                     Py_TYPE(ob)->tp_name, ct->ct_name);
-    return NULL;
-}
-
-static PyObject *b_cast(PyObject *self, PyObject *args)
-{
-    CTypeDescrObject *ct;
-    PyObject *ob;
-    if (!PyArg_ParseTuple(args, "O!O:cast", &CTypeDescr_Type, &ct, &ob))
-        return NULL;
-
-    return do_cast(ct, ob);
-}
-
-/************************************************************/
-
-typedef struct {
-    PyObject_HEAD
-    void *dl_handle;
-    char *dl_name;
-    int dl_auto_close;
-} DynLibObject;
-
-static void dl_dealloc(DynLibObject *dlobj)
-{
-    if (dlobj->dl_handle != NULL && dlobj->dl_auto_close)
-        dlclose(dlobj->dl_handle);
-    free(dlobj->dl_name);
-    PyObject_Del(dlobj);
-}
-
-static PyObject *dl_repr(DynLibObject *dlobj)
-{
-    return PyText_FromFormat("<clibrary '%s'>", dlobj->dl_name);
-}
-
-static int dl_check_closed(DynLibObject *dlobj)
-{
-    if (dlobj->dl_handle == NULL)
-    {
-        PyErr_Format(PyExc_ValueError, "library '%s' has already been closed",
-                     dlobj->dl_name);
-        return -1;
-    }
-    return 0;
-}
-
-static PyObject *dl_load_function(DynLibObject *dlobj, PyObject *args)
-{
-    CTypeDescrObject *ct;
-    char *funcname;
-    void *funcptr;
-
-    if (!PyArg_ParseTuple(args, "O!s:load_function",
-                          &CTypeDescr_Type, &ct, &funcname))
-        return NULL;
-
-    if (dl_check_closed(dlobj) < 0)
-        return NULL;
-
-    if (!(ct->ct_flags & (CT_FUNCTIONPTR | CT_POINTER | CT_ARRAY))) {
-        PyErr_Format(PyExc_TypeError,
-                     "function or pointer or array cdata expected, got '%s'",
-                     ct->ct_name);
-        return NULL;
-    }
-    dlerror();   /* clear error condition */
-    funcptr = dlsym(dlobj->dl_handle, funcname);
-    if (funcptr == NULL) {
-        const char *error = dlerror();
-        PyErr_Format(PyExc_AttributeError,
-                     "function/symbol '%s' not found in library '%s': %s",
-                     funcname, dlobj->dl_name, error);
-        return NULL;
-    }
-
-    if ((ct->ct_flags & CT_ARRAY) && ct->ct_length < 0) {
-        ct = (CTypeDescrObject *)ct->ct_stuff;
-    }
-    return new_simple_cdata(funcptr, ct);
-}
-
-static PyObject *dl_read_variable(DynLibObject *dlobj, PyObject *args)
-{
-    CTypeDescrObject *ct;
-    char *varname;
-    char *data;
-
-    if (!PyArg_ParseTuple(args, "O!s:read_variable",
-                          &CTypeDescr_Type, &ct, &varname))
-        return NULL;
-
-    if (dl_check_closed(dlobj) < 0)
-        return NULL;
-
-    dlerror();   /* clear error condition */
-    data = dlsym(dlobj->dl_handle, varname);
-    if (data == NULL) {
-        const char *error = dlerror();
-        if (error != NULL) {
-            PyErr_Format(PyExc_KeyError,
-                         "variable '%s' not found in library '%s': %s",
-                         varname, dlobj->dl_name, error);
-            return NULL;
-        }
-    }
-    return convert_to_object(data, ct);
-}
-
-static PyObject *dl_write_variable(DynLibObject *dlobj, PyObject *args)
-{
-    CTypeDescrObject *ct;
-    PyObject *value;
-    char *varname;
-    char *data;
-
-    if (!PyArg_ParseTuple(args, "O!sO:write_variable",
-                          &CTypeDescr_Type, &ct, &varname, &value))
-        return NULL;
-
-    if (dl_check_closed(dlobj) < 0)
-        return NULL;
-
-    dlerror();   /* clear error condition */
-    data = dlsym(dlobj->dl_handle, varname);
-    if (data == NULL) {
-        const char *error = dlerror();
-        PyErr_Format(PyExc_KeyError,
-                     "variable '%s' not found in library '%s': %s",
-                     varname, dlobj->dl_name, error);
-        return NULL;
-    }
-    if (convert_from_object(data, ct, value) < 0)
-        return NULL;
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *dl_close_lib(DynLibObject *dlobj, PyObject *no_args)
-{
-    if (dlobj->dl_handle != NULL)
-    {
-        dlclose(dlobj->dl_handle);
-        dlobj->dl_handle = NULL;
-    }
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyMethodDef dl_methods[] = {
-    {"load_function",   (PyCFunction)dl_load_function,  METH_VARARGS},
-    {"read_variable",   (PyCFunction)dl_read_variable,  METH_VARARGS},
-    {"write_variable",  (PyCFunction)dl_write_variable, METH_VARARGS},
-    {"close_lib",       (PyCFunction)dl_close_lib,      METH_NOARGS},
-    {NULL,              NULL}           /* sentinel */
-};
-
-static PyTypeObject dl_type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.CLibrary",           /* tp_name */
-    sizeof(DynLibObject),               /* tp_basicsize */
-    0,                                  /* tp_itemsize */
-    /* methods */
-    (destructor)dl_dealloc,             /* tp_dealloc */
-    0,                                  /* tp_print */
-    0,                                  /* tp_getattr */
-    0,                                  /* tp_setattr */
-    0,                                  /* tp_compare */
-    (reprfunc)dl_repr,                  /* tp_repr */
-    0,                                  /* tp_as_number */
-    0,                                  /* tp_as_sequence */
-    0,                                  /* tp_as_mapping */
-    0,                                  /* tp_hash */
-    0,                                  /* tp_call */
-    0,                                  /* tp_str */
-    PyObject_GenericGetAttr,            /* tp_getattro */
-    0,                                  /* tp_setattro */
-    0,                                  /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
-    0,                                  /* tp_doc */
-    0,                                  /* tp_traverse */
-    0,                                  /* tp_clear */
-    0,                                  /* tp_richcompare */
-    0,                                  /* tp_weaklistoffset */
-    0,                                  /* tp_iter */
-    0,                                  /* tp_iternext */
-    dl_methods,                         /* tp_methods */
-};
-
-static void *b_do_dlopen(PyObject *args, const char **p_printable_filename,
-                         PyObject **p_temp, int *auto_close)
-{
-    /* Logic to call the correct version of dlopen().  Returns NULL in case of error.
-       Otherwise, '*p_printable_filename' will point to a printable char version of
-       the filename (maybe utf-8-encoded).  '*p_temp' will be set either to NULL or
-       to a temporary object that must be freed after looking at printable_filename.
-    */
-    void *handle;
-    char *filename_or_null;
-    int flags = 0;
-    *p_temp = NULL;
-    *auto_close = 1;
-    
-    if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_ITEM(args, 0) == Py_None) {
-        PyObject *dummy;
-        if (!PyArg_ParseTuple(args, "|Oi:load_library",
-                              &dummy, &flags))
-            return NULL;
-        filename_or_null = NULL;
-        *p_printable_filename = "<None>";
-    }
-    else if (CData_Check(PyTuple_GET_ITEM(args, 0)))
-    {
-        CDataObject *cd;
-        if (!PyArg_ParseTuple(args, "O|i:load_library", &cd, &flags))
-            return NULL;
-        /* 'flags' is accepted but ignored in this case */
-        if ((cd->c_type->ct_flags & CT_IS_VOID_PTR) == 0) {
-            PyErr_Format(PyExc_TypeError,
-                "dlopen() takes a file name or 'void *' handle, not '%s'",
-                cd->c_type->ct_name);
-            return NULL;
-        }
-        handle = cd->c_data;
-        if (handle == NULL) {
-            PyErr_Format(PyExc_RuntimeError, "cannot call dlopen(NULL)");
-            return NULL;
-        }
-        *p_temp = PyText_FromFormat("%p", handle);
-        *p_printable_filename = PyText_AsUTF8(*p_temp);
-        *auto_close = 0;
-        return handle;
-    }
-    else
-    {
-        PyObject *s = PyTuple_GET_ITEM(args, 0);
-#ifdef MS_WIN32
-        PyObject *filename_unicode;
-        if (PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags))
-        {
-            Py_ssize_t sz1;
-            wchar_t *w1;
-#if PY_MAJOR_VERSION < 3
-            s = PyUnicode_AsUTF8String(s);
-            if (s == NULL)
-                return NULL;
-            *p_temp = s;
-#endif
-            *p_printable_filename = PyText_AsUTF8(s);
-            if (*p_printable_filename == NULL)
-                return NULL;
-
-            sz1 = PyUnicode_GetSize(filename_unicode) + 1;
-            sz1 *= 2;   /* should not be needed, but you never know */
-            w1 = alloca(sizeof(wchar_t) * sz1);
-            sz1 = PyUnicode_AsWideChar((PyUnicodeObject *)filename_unicode,
-                                       w1, sz1 - 1);
-            if (sz1 < 0)
-                return NULL;
-            w1[sz1] = 0;
-            handle = dlopenW(w1);
-            goto got_handle;
-        }
-        PyErr_Clear();
-#endif
-        if (!PyArg_ParseTuple(args, "et|i:load_library",
-                     Py_FileSystemDefaultEncoding, &filename_or_null, &flags))
-            return NULL;
-#if PY_MAJOR_VERSION < 3
-        if (PyUnicode_Check(s))
-        {
-            s = PyUnicode_AsUTF8String(s);
-            if (s == NULL) {
-                PyMem_Free(filename_or_null);
-                return NULL;
-            }
-            *p_temp = s;
-        }
-#endif
-        *p_printable_filename = PyText_AsUTF8(s);
-        if (*p_printable_filename == NULL) {
-            PyMem_Free(filename_or_null);
-            return NULL;
-        }
-    }
-    if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0)
-        flags |= RTLD_NOW;
-
-#ifdef MS_WIN32
-    if (filename_or_null == NULL) {
-        PyErr_SetString(PyExc_OSError, "dlopen(None) not supported on Windows");
-        return NULL;
-    }
-#endif
-
-    handle = dlopen(filename_or_null, flags);
-    PyMem_Free(filename_or_null);
-
-#ifdef MS_WIN32
-  got_handle:
-#endif
-    if (handle == NULL) {
-        const char *error = dlerror();
-        PyErr_Format(PyExc_OSError, "cannot load library '%s': %s",
-                     *p_printable_filename, error);
-        return NULL;
-    }
-    return handle;
-}
-
-static PyObject *b_load_library(PyObject *self, PyObject *args)
-{
-    const char *printable_filename;
-    PyObject *temp;
-    void *handle;
-    DynLibObject *dlobj = NULL;
-    int auto_close;
-
-    handle = b_do_dlopen(args, &printable_filename, &temp, &auto_close);
-    if (handle == NULL)
-        goto error;
-
-    dlobj = PyObject_New(DynLibObject, &dl_type);
-    if (dlobj == NULL) {
-        dlclose(handle);
-        goto error;
-    }
-    dlobj->dl_handle = handle;
-    dlobj->dl_name = strdup(printable_filename);
-    dlobj->dl_auto_close = auto_close;
- 
- error:
-    Py_XDECREF(temp);
-    return (PyObject *)dlobj;
-}
-
-/************************************************************/
-
-static PyObject *get_unique_type(CTypeDescrObject *x,
-                                 const void *unique_key[], long keylength)
-{
-    /* Replace the CTypeDescrObject 'x' with a standardized one.
-       This either just returns x, or x is decrefed and a new reference
-       to the already-existing equivalent is returned.
-
-       In this function, 'x' always contains a reference that must be
-       either decrefed or returned.
-
-       Keys:
-           void       ["void"]
-           primitive  [&static_struct]
-           pointer    [ctype]
-           array      [ctype, length]
-           funcptr    [ctresult, ellipsis+abi, num_args, ctargs...]
-    */
-    PyObject *key, *y;
-    void *pkey;
-
-    key = PyBytes_FromStringAndSize(NULL, keylength * sizeof(void *));
-    if (key == NULL)
-        goto error;
-
-    pkey = PyBytes_AS_STRING(key);
-    memcpy(pkey, unique_key, keylength * sizeof(void *));
-
-    y = PyDict_GetItem(unique_cache, key);
-    if (y != NULL) {
-        Py_DECREF(key);
-        Py_INCREF(y);
-        Py_DECREF(x);
-        return y;
-    }
-    if (PyDict_SetItem(unique_cache, key, (PyObject *)x) < 0) {
-        Py_DECREF(key);
-        goto error;
-    }
-    /* Haaaack for our reference count hack: gcmodule.c must not see this
-       dictionary.  The problem is that any PyDict_SetItem() notices that
-       'x' is tracked and re-tracks the unique_cache dictionary.  So here
-       we re-untrack it again... */
-    PyObject_GC_UnTrack(unique_cache);
-
-    assert(x->ct_unique_key == NULL);
-    x->ct_unique_key = key; /* the key will be freed in ctypedescr_dealloc() */
-    /* the 'value' in unique_cache doesn't count as 1, but don't use
-       Py_DECREF(x) here because it will confuse debug builds into thinking
-       there was an extra DECREF in total. */
-    ((PyObject *)x)->ob_refcnt--;
-    return (PyObject *)x;
-
- error:
-    Py_DECREF(x);
-    return NULL;
-}
-
-/* according to the C standard, these types should be equivalent to the
-   _Complex types for the purposes of storage (not arguments in calls!) */
-typedef float cffi_float_complex_t[2];
-typedef double cffi_double_complex_t[2];
-
-static PyObject *new_primitive_type(const char *name)
-{
-#define ENUM_PRIMITIVE_TYPES                                    \
-       EPTYPE(c, char, CT_PRIMITIVE_CHAR)                       \
-       EPTYPE(s, short, CT_PRIMITIVE_SIGNED )                   \
-       EPTYPE(i, int, CT_PRIMITIVE_SIGNED )                     \
-       EPTYPE(l, long, CT_PRIMITIVE_SIGNED )                    \
-       EPTYPE(ll, long long, CT_PRIMITIVE_SIGNED )              \
-       EPTYPE(sc, signed char, CT_PRIMITIVE_SIGNED )            \
-       EPTYPE(uc, unsigned char, CT_PRIMITIVE_UNSIGNED )        \
-       EPTYPE(us, unsigned short, CT_PRIMITIVE_UNSIGNED )       \
-       EPTYPE(ui, unsigned int, CT_PRIMITIVE_UNSIGNED )         \
-       EPTYPE(ul, unsigned long, CT_PRIMITIVE_UNSIGNED )        \
-       EPTYPE(ull, unsigned long long, CT_PRIMITIVE_UNSIGNED )  \
-       EPTYPE(f, float, CT_PRIMITIVE_FLOAT )                    \
-       EPTYPE(d, double, CT_PRIMITIVE_FLOAT )                   \
-       EPTYPE(ld, long double, CT_PRIMITIVE_FLOAT | CT_IS_LONGDOUBLE ) \
-       EPTYPE2(fc, "float _Complex", cffi_float_complex_t, CT_PRIMITIVE_COMPLEX ) \
-       EPTYPE2(dc, "double _Complex", cffi_double_complex_t, CT_PRIMITIVE_COMPLEX ) \
-       ENUM_PRIMITIVE_TYPES_WCHAR                               \
-       EPTYPE2(c16, "char16_t", cffi_char16_t, CT_PRIMITIVE_CHAR ) \
-       EPTYPE2(c32, "char32_t", cffi_char32_t, CT_PRIMITIVE_CHAR ) \
-       EPTYPE(b, _Bool, CT_PRIMITIVE_UNSIGNED | CT_IS_BOOL )    \
-     /* the following types are not primitive in the C sense */ \
-       EPTYPE(i8, int8_t, CT_PRIMITIVE_SIGNED)                  \
-       EPTYPE(u8, uint8_t, CT_PRIMITIVE_UNSIGNED)               \
-       EPTYPE(i16, int16_t, CT_PRIMITIVE_SIGNED)                \
-       EPTYPE(u16, uint16_t, CT_PRIMITIVE_UNSIGNED)             \
-       EPTYPE(i32, int32_t, CT_PRIMITIVE_SIGNED)                \
-       EPTYPE(u32, uint32_t, CT_PRIMITIVE_UNSIGNED)             \
-       EPTYPE(i64, int64_t, CT_PRIMITIVE_SIGNED)                \
-       EPTYPE(u64, uint64_t, CT_PRIMITIVE_UNSIGNED)             \
-       EPTYPE(il8, int_least8_t, CT_PRIMITIVE_SIGNED)           \
-       EPTYPE(ul8, uint_least8_t, CT_PRIMITIVE_UNSIGNED)        \
-       EPTYPE(il16, int_least16_t, CT_PRIMITIVE_SIGNED)         \
-       EPTYPE(ul16, uint_least16_t, CT_PRIMITIVE_UNSIGNED)      \
-       EPTYPE(il32, int_least32_t, CT_PRIMITIVE_SIGNED)         \
-       EPTYPE(ul32, uint_least32_t, CT_PRIMITIVE_UNSIGNED)      \
-       EPTYPE(il64, int_least64_t, CT_PRIMITIVE_SIGNED)         \
-       EPTYPE(ul64, uint_least64_t, CT_PRIMITIVE_UNSIGNED)      \
-       EPTYPE(if8, int_fast8_t, CT_PRIMITIVE_SIGNED)            \
-       EPTYPE(uf8, uint_fast8_t, CT_PRIMITIVE_UNSIGNED)         \
-       EPTYPE(if16, int_fast16_t, CT_PRIMITIVE_SIGNED)          \
-       EPTYPE(uf16, uint_fast16_t, CT_PRIMITIVE_UNSIGNED)       \
-       EPTYPE(if32, int_fast32_t, CT_PRIMITIVE_SIGNED)          \
-       EPTYPE(uf32, uint_fast32_t, CT_PRIMITIVE_UNSIGNED)       \
-       EPTYPE(if64, int_fast64_t, CT_PRIMITIVE_SIGNED)          \
-       EPTYPE(uf64, uint_fast64_t, CT_PRIMITIVE_UNSIGNED)       \
-       EPTYPE(ip, intptr_t, CT_PRIMITIVE_SIGNED)                \
-       EPTYPE(up, uintptr_t, CT_PRIMITIVE_UNSIGNED)             \
-       EPTYPE(im, intmax_t, CT_PRIMITIVE_SIGNED)                \
-       EPTYPE(um, uintmax_t, CT_PRIMITIVE_UNSIGNED)             \
-       EPTYPE(pd, ptrdiff_t, CT_PRIMITIVE_SIGNED)               \
-       EPTYPE(sz, size_t, CT_PRIMITIVE_UNSIGNED)                \
-       EPTYPE2(ssz, "ssize_t", Py_ssize_t, CT_PRIMITIVE_SIGNED)
-
-#ifdef HAVE_WCHAR_H
-# define ENUM_PRIMITIVE_TYPES_WCHAR                             \
-       EPTYPE(wc, wchar_t, CT_PRIMITIVE_CHAR |                  \
-                           (((wchar_t)-1) > 0 ? 0 : CT_IS_SIGNED_WCHAR))
-#else
-# define ENUM_PRIMITIVE_TYPES_WCHAR   /* nothing */
-#endif
-
-#define EPTYPE(code, typename, flags)  EPTYPE2(code, #typename, typename, flags)
-
-#define EPTYPE2(code, export_name, typename, flags)     \
-    struct aligncheck_##code { char x; typename y; };
-    ENUM_PRIMITIVE_TYPES
-#undef EPTYPE2
-
-    CTypeDescrObject *td;
-    static const struct descr_s { const char *name; int size, align, flags; }
-    types[] = {
-#define EPTYPE2(code, export_name, typename, flags)     \
-        { export_name,                                  \
-          sizeof(typename),                             \
-          offsetof(struct aligncheck_##code, y),        \
-          flags                                         \
-        },
-    ENUM_PRIMITIVE_TYPES
-#undef EPTYPE2
-#undef EPTYPE
-#undef ENUM_PRIMITIVE_TYPES_WCHAR
-#undef ENUM_PRIMITIVE_TYPES
-        { NULL }
-    };
-    const struct descr_s *ptypes;
-    const void *unique_key[1];
-    int name_size;
-    ffi_type *ffitype;
-
-    for (ptypes=types; ; ptypes++) {
-        if (ptypes->name == NULL) {
-#ifndef HAVE_WCHAR_H
-            if (strcmp(name, "wchar_t"))
-                PyErr_SetString(PyExc_NotImplementedError, name);
-            else
-#endif
-            PyErr_SetString(PyExc_KeyError, name);
-            return NULL;
-        }
-        if (strcmp(name, ptypes->name) == 0)
-            break;
-    }
-
-    if (ptypes->flags & CT_PRIMITIVE_SIGNED) {
-        switch (ptypes->size) {
-        case 1: ffitype = &ffi_type_sint8; break;
-        case 2: ffitype = &ffi_type_sint16; break;
-        case 4: ffitype = &ffi_type_sint32; break;
-        case 8: ffitype = &ffi_type_sint64; break;
-        default: goto bad_ffi_type;
-        }
-    }
-    else if (ptypes->flags & CT_PRIMITIVE_FLOAT) {
-        if (strcmp(ptypes->name, "float") == 0)
-            ffitype = &ffi_type_float;
-        else if (strcmp(ptypes->name, "double") == 0)
-            ffitype = &ffi_type_double;
-        else if (strcmp(ptypes->name, "long double") == 0) {
-            /* assume that if sizeof(double) == sizeof(long double), then
-               the two types are equivalent for C.  libffi bugs on Win64
-               if a function's return type is ffi_type_longdouble... */
-            if (sizeof(double) == sizeof(long double))
-                ffitype = &ffi_type_double;
-            else
-                ffitype = &ffi_type_longdouble;
-        }
-        else
-            goto bad_ffi_type;
-    }
-    else if (ptypes->flags & CT_PRIMITIVE_COMPLEX) {
-        /* As of March 2017, still no libffi support for complex.
-           It fails silently if we try to use ffi_type_complex_float
-           or ffi_type_complex_double.  Better not use it at all.
-         */
-        ffitype = NULL;
-    }
-    else {
-        switch (ptypes->size) {
-        case 1: ffitype = &ffi_type_uint8; break;
-        case 2: ffitype = &ffi_type_uint16; break;
-        case 4: ffitype = &ffi_type_uint32; break;
-        case 8: ffitype = &ffi_type_uint64; break;
-        default: goto bad_ffi_type;
-        }
-    }
-
-    name_size = strlen(ptypes->name) + 1;
-    td = ctypedescr_new(name_size);
-    if (td == NULL)
-        return NULL;
-
-    memcpy(td->ct_name, name, name_size);
-    td->ct_size = ptypes->size;
-    td->ct_length = ptypes->align;
-    td->ct_extra = ffitype;
-    td->ct_flags = ptypes->flags;
-    if (td->ct_flags & (CT_PRIMITIVE_SIGNED | CT_PRIMITIVE_CHAR)) {
-        if (td->ct_size <= (Py_ssize_t)sizeof(long))
-            td->ct_flags |= CT_PRIMITIVE_FITS_LONG;
-    }
-    else if (td->ct_flags & CT_PRIMITIVE_UNSIGNED) {
-        if (td->ct_size < (Py_ssize_t)sizeof(long))
-            td->ct_flags |= CT_PRIMITIVE_FITS_LONG;
-    }
-    td->ct_name_position = strlen(td->ct_name);
-    unique_key[0] = ptypes;
-    return get_unique_type(td, unique_key, 1);
-
- bad_ffi_type:
-    PyErr_Format(PyExc_NotImplementedError,
-                 "primitive type '%s' has size %d; "
-                 "the supported sizes are 1, 2, 4, 8",
-                 name, (int)ptypes->size);
-    return NULL;
-}
-
-static PyObject *b_new_primitive_type(PyObject *self, PyObject *args)
-{
-    char *name;
-    if (!PyArg_ParseTuple(args, "s:new_primitive_type", &name))
-        return NULL;
-    return new_primitive_type(name);
-}
-
-static PyObject *new_pointer_type(CTypeDescrObject *ctitem)
-{
-    CTypeDescrObject *td;
-    const char *extra;
-    const void *unique_key[1];
-
-    if (ctitem->ct_flags & CT_ARRAY)
-        extra = "(*)";   /* obscure case: see test_array_add */
-    else
-        extra = " *";
-    td = ctypedescr_new_on_top(ctitem, extra, 2);
-    if (td == NULL)
-        return NULL;
-
-    td->ct_size = sizeof(void *);
-    td->ct_length = -1;
-    td->ct_flags = CT_POINTER;
-    if (ctitem->ct_flags & (CT_STRUCT|CT_UNION))
-        td->ct_flags |= CT_IS_PTR_TO_OWNED;
-    if (ctitem->ct_flags & CT_VOID)
-        td->ct_flags |= CT_IS_VOID_PTR;
-    if ((ctitem->ct_flags & CT_VOID) ||
-        ((ctitem->ct_flags & CT_PRIMITIVE_CHAR) &&
-         ctitem->ct_size == sizeof(char)))
-        td->ct_flags |= CT_IS_VOIDCHAR_PTR;   /* 'void *' or 'char *' only */
-    unique_key[0] = ctitem;
-    return get_unique_type(td, unique_key, 1);
-}
-
-static PyObject *b_new_pointer_type(PyObject *self, PyObject *args)
-{
-    CTypeDescrObject *ctitem;
-    if (!PyArg_ParseTuple(args, "O!:new_pointer_type",
-                          &CTypeDescr_Type, &ctitem))
-        return NULL;
-    return new_pointer_type(ctitem);
-}
-
-static PyObject *b_new_array_type(PyObject *self, PyObject *args)
-{
-    PyObject *lengthobj;
-    Py_ssize_t length;
-    CTypeDescrObject *ctptr;
-
-    if (!PyArg_ParseTuple(args, "O!O:new_array_type",
-                          &CTypeDescr_Type, &ctptr, &lengthobj))
-        return NULL;
-
-    if (lengthobj == Py_None) {
-        length = -1;
-    }
-    else {
-        length = PyNumber_AsSsize_t(lengthobj, PyExc_OverflowError);
-        if (length < 0) {
-            if (!PyErr_Occurred())
-                PyErr_SetString(PyExc_ValueError, "negative array length");
-            return NULL;
-        }
-    }
-    return new_array_type(ctptr, length);
-}
-
-static PyObject *
-new_array_type(CTypeDescrObject *ctptr, Py_ssize_t length)
-{
-    CTypeDescrObject *td, *ctitem;
-    char extra_text[32];
-    Py_ssize_t arraysize;
-    int flags = CT_ARRAY;
-    const void *unique_key[2];
-
-    if (!(ctptr->ct_flags & CT_POINTER)) {
-        PyErr_SetString(PyExc_TypeError, "first arg must be a pointer ctype");
-        return NULL;
-    }
-    ctitem = ctptr->ct_itemdescr;
-    if (ctitem->ct_size < 0) {
-        PyErr_Format(PyExc_ValueError, "array item of unknown size: '%s'",
-                     ctitem->ct_name);
-        return NULL;
-    }
-
-    if (length < 0) {
-        sprintf(extra_text, "[]");
-        length = -1;
-        arraysize = -1;
-    }
-    else {
-        sprintf(extra_text, "[%llu]", (unsigned PY_LONG_LONG)length);
-        arraysize = MUL_WRAPAROUND(length, ctitem->ct_size);
-        if (length > 0 && (arraysize / length) != ctitem->ct_size) {
-            PyErr_SetString(PyExc_OverflowError,
-                            "array size would overflow a Py_ssize_t");
-            return NULL;
-        }
-    }
-    td = ctypedescr_new_on_top(ctitem, extra_text, 0);
-    if (td == NULL)
-        return NULL;
-
-    Py_INCREF(ctptr);
-    td->ct_stuff = (PyObject *)ctptr;
-    td->ct_size = arraysize;
-    td->ct_length = length;
-    td->ct_flags = flags;
-    unique_key[0] = ctptr;
-    unique_key[1] = (void *)length;
-    return get_unique_type(td, unique_key, 2);
-}
-
-static PyObject *new_void_type(void)
-{
-    int name_size = strlen("void") + 1;
-    const void *unique_key[1];
-    CTypeDescrObject *td = ctypedescr_new(name_size);
-    if (td == NULL)
-        return NULL;
-
-    memcpy(td->ct_name, "void", name_size);
-    td->ct_size = -1;
-    td->ct_flags = CT_VOID | CT_IS_OPAQUE;
-    td->ct_name_position = strlen("void");
-    unique_key[0] = "void";
-    return get_unique_type(td, unique_key, 1);
-}
-
-static PyObject *b_new_void_type(PyObject *self, PyObject *args)
-{
-    return new_void_type();
-}
-
-static PyObject *new_struct_or_union_type(const char *name, int flag)
-{
-    int namelen = strlen(name);
-    CTypeDescrObject *td = ctypedescr_new(namelen + 1);
-    if (td == NULL)
-        return NULL;
-
-    td->ct_size = -1;
-    td->ct_length = -1;
-    td->ct_flags = flag | CT_IS_OPAQUE;
-    td->ct_extra = NULL;
-    memcpy(td->ct_name, name, namelen + 1);
-    td->ct_name_position = namelen;
-    return (PyObject *)td;
-}
-
-static PyObject *b_new_struct_type(PyObject *self, PyObject *args)
-{
-    char *name;
-    int flag;
-    if (!PyArg_ParseTuple(args, "s:new_struct_type", &name))
-        return NULL;
-
-    flag = CT_STRUCT;
-    if (strcmp(name, "struct _IO_FILE") == 0 || strcmp(name, "FILE") == 0)
-        flag |= CT_IS_FILE;
-    return new_struct_or_union_type(name, flag);
-}
-
-static PyObject *b_new_union_type(PyObject *self, PyObject *args)
-{
-    char *name;
-    if (!PyArg_ParseTuple(args, "s:new_union_type", &name))
-        return NULL;
-    return new_struct_or_union_type(name, CT_UNION);
-}
-
-static CFieldObject *
-_add_field(PyObject *interned_fields, PyObject *fname, CTypeDescrObject *ftype,
-           Py_ssize_t offset, int bitshift, int fbitsize, int flags)
-{
-    int err;
-    Py_ssize_t prev_size;
-    CFieldObject *cf = PyObject_New(CFieldObject, &CField_Type);
-    if (cf == NULL)
-        return NULL;
-
-    Py_INCREF(ftype);
-    cf->cf_type = ftype;
-    cf->cf_offset = offset;
-    cf->cf_bitshift = bitshift;
-    cf->cf_bitsize = fbitsize;
-    cf->cf_flags = flags;
-
-    Py_INCREF(fname);
-    PyText_InternInPlace(&fname);
-    prev_size = PyDict_Size(interned_fields);
-    err = PyDict_SetItem(interned_fields, fname, (PyObject *)cf);
-    Py_DECREF(fname);
-    Py_DECREF(cf);
-    if (err < 0)
-        return NULL;
-
-    if (PyDict_Size(interned_fields) != prev_size + 1) {
-        PyErr_Format(PyExc_KeyError, "duplicate field name '%s'",
-                     PyText_AS_UTF8(fname));
-        return NULL;
-    }
-    return cf;   /* borrowed reference */
-}
-
-#define SF_MSVC_BITFIELDS     0x01
-#define SF_GCC_ARM_BITFIELDS  0x02
-#define SF_GCC_X86_BITFIELDS  0x10
-
-#define SF_GCC_BIG_ENDIAN     0x04
-#define SF_GCC_LITTLE_ENDIAN  0x40
-
-#define SF_PACKED             0x08
-#define SF_STD_FIELD_POS      0x80
-
-#ifdef MS_WIN32
-#  define SF_DEFAULT_PACKING     8
-#else
-#  define SF_DEFAULT_PACKING   0x40000000   /* a huge power of two */
-#endif
-
-static int complete_sflags(int sflags)
-{
-    /* add one of the SF_xxx_BITFIELDS flags if none is specified */
-    if (!(sflags & (SF_MSVC_BITFIELDS | SF_GCC_ARM_BITFIELDS |
-                    SF_GCC_X86_BITFIELDS))) {
-#ifdef MS_WIN32
-        sflags |= SF_MSVC_BITFIELDS;
-#else
-# if defined(__APPLE__) && defined(__arm64__)
-        sflags |= SF_GCC_X86_BITFIELDS;
-# elif defined(__arm__) || defined(__aarch64__)
-        sflags |= SF_GCC_ARM_BITFIELDS;
-# else
-        sflags |= SF_GCC_X86_BITFIELDS;
-# endif
-#endif
-    }
-    /* add one of SF_GCC_xx_ENDIAN if none is specified */
-    if (!(sflags & (SF_GCC_BIG_ENDIAN | SF_GCC_LITTLE_ENDIAN))) {
-        int _check_endian = 1;
-        if (*(char *)&_check_endian == 0)
-            sflags |= SF_GCC_BIG_ENDIAN;
-        else
-            sflags |= SF_GCC_LITTLE_ENDIAN;
-    }
-    return sflags;
-}
-
-static int detect_custom_layout(CTypeDescrObject *ct, int sflags,
-                                Py_ssize_t cdef_value,
-                                Py_ssize_t compiler_value,
-                                const char *msg1, const char *txt,
-                                const char *msg2)
-{
-    if (compiler_value != cdef_value) {
-        if (sflags & SF_STD_FIELD_POS) {
-            PyErr_Format(FFIError,
-                         "%s: %s%s%s (cdef says %zd, but C compiler says %zd)."
-                         " fix it or use \"...;\" as the last field in the "
-                         "cdef for %s to make it flexible",
-                         ct->ct_name, msg1, txt, msg2,
-                         cdef_value, compiler_value,
-                         ct->ct_name);
-            return -1;
-        }
-        ct->ct_flags |= CT_CUSTOM_FIELD_POS;
-    }
-    return 0;
-}
-
-#define ROUNDUP_BYTES(bytes, bits)    ((bytes) + ((bits) > 0))
-
-static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args)
-{
-    CTypeDescrObject *ct;
-    PyObject *fields, *interned_fields, *ignored;
-    int is_union, alignment;
-    Py_ssize_t byteoffset, i, nb_fields, byteoffsetmax, alignedsize;
-    int bitoffset;
-    Py_ssize_t byteoffsetorg;
-    Py_ssize_t totalsize = -1;
-    int totalalignment = -1;
-    CFieldObject **previous;
-    int prev_bitfield_size, prev_bitfield_free;
-    int sflags = 0, fflags;
-    int pack = 0;
-
-    if (!PyArg_ParseTuple(args, "O!O!|Oniii:complete_struct_or_union",
-                          &CTypeDescr_Type, &ct,
-                          &PyList_Type, &fields,
-                          &ignored, &totalsize, &totalalignment, &sflags,
-                          &pack))
-        return NULL;
-
-    sflags = complete_sflags(sflags);
-    if (sflags & SF_PACKED)
-        pack = 1;
-    else if (pack <= 0)
-        pack = SF_DEFAULT_PACKING;
-    else
-        sflags |= SF_PACKED;
-
-    if ((ct->ct_flags & (CT_STRUCT|CT_IS_OPAQUE)) ==
-                        (CT_STRUCT|CT_IS_OPAQUE)) {
-        is_union = 0;
-    }
-    else if ((ct->ct_flags & (CT_UNION|CT_IS_OPAQUE)) ==
-                             (CT_UNION|CT_IS_OPAQUE)) {
-        is_union = 1;
-    }
-    else {
-        PyErr_SetString(PyExc_TypeError,
-                  "first arg must be a non-initialized struct or union ctype");
-        return NULL;
-    }
-    ct->ct_flags &= ~(CT_CUSTOM_FIELD_POS | CT_WITH_PACKED_CHANGE);
-
-    alignment = 1;
-    byteoffset = 0;     /* the real value is 'byteoffset+bitoffset*8', which */
-    bitoffset = 0;      /* counts the offset in bits */
-    byteoffsetmax = 0; /* the maximum value of byteoffset-rounded-up-to-byte */
-    prev_bitfield_size = 0;
-    prev_bitfield_free = 0;
-    nb_fields = PyList_GET_SIZE(fields);
-    interned_fields = PyDict_New();
-    if (interned_fields == NULL)
-        return NULL;
-
-    previous = (CFieldObject **)&ct->ct_extra;
-
-    for (i=0; i<nb_fields; i++) {
-        PyObject *fname;
-        CTypeDescrObject *ftype;
-        int fbitsize = -1, falign, falignorg, do_align;
-        Py_ssize_t foffset = -1;
-
-        if (!PyArg_ParseTuple(PyList_GET_ITEM(fields, i), "O!O!|in:list item",
-                              &PyText_Type, &fname,
-                              &CTypeDescr_Type, &ftype,
-                              &fbitsize, &foffset))
-            goto error;
-
-        if (ftype->ct_size < 0) {
-            if ((ftype->ct_flags & CT_ARRAY) && fbitsize < 0
-                    && (i == nb_fields - 1 || foffset != -1)) {
-                ct->ct_flags |= CT_WITH_VAR_ARRAY;
-            }
-            else {
-                PyErr_Format(PyExc_TypeError,
-                             "field '%s.%s' has ctype '%s' of unknown size",
-                             ct->ct_name, PyText_AS_UTF8(fname),
-                             ftype->ct_name);
-                goto error;
-            }
-        }
-        else if (ftype->ct_flags & (CT_STRUCT|CT_UNION)) {
-            if (force_lazy_struct(ftype) < 0)   /* for CT_WITH_VAR_ARRAY */
-                return NULL;
-
-            /* GCC (or maybe C99) accepts var-sized struct fields that are not
-               the last field of a larger struct.  That's why there is no
-               check here for "last field": we propagate the flag
-               CT_WITH_VAR_ARRAY to any struct that contains either an open-
-               ended array or another struct that recursively contains an
-               open-ended array. */
-            if (ftype->ct_flags & CT_WITH_VAR_ARRAY)
-                ct->ct_flags |= CT_WITH_VAR_ARRAY;
-        }
-
-        if (is_union)
-            byteoffset = bitoffset = 0;   /* reset each field at offset 0 */
-
-        /* update the total alignment requirement, but skip it if the
-           field is an anonymous bitfield or if SF_PACKED */
-        falignorg = get_alignment(ftype);
-        if (falignorg < 0)
-            goto error;
-        falign = (pack < falignorg) ? pack : falignorg;
-
-        do_align = 1;
-        if (!(sflags & SF_GCC_ARM_BITFIELDS) && fbitsize >= 0) {
-            if (!(sflags & SF_MSVC_BITFIELDS)) {
-                /* GCC: anonymous bitfields (of any size) don't cause alignment */
-                do_align = PyText_GetSize(fname) > 0;
-            }
-            else {
-                /* MSVC: zero-sized bitfields don't cause alignment */
-                do_align = fbitsize > 0;
-            }
-        }
-        if (alignment < falign && do_align)
-            alignment = falign;
-
-        fflags = (is_union && i > 0) ? BF_IGNORE_IN_CTOR : 0;
-
-        if (fbitsize < 0) {
-            /* not a bitfield: common case */
-            int bs_flag;
-
-            if ((ftype->ct_flags & CT_ARRAY) && ftype->ct_length <= 0)
-                bs_flag = BS_EMPTY_ARRAY;
-            else
-                bs_flag = BS_REGULAR;
-
-            /* align this field to its own 'falign' by inserting padding */
-
-            /* first, pad to the next byte,
-             * then pad to 'falign' or 'falignorg' bytes */
-            byteoffset = ROUNDUP_BYTES(byteoffset, bitoffset);
-            bitoffset = 0;
-            byteoffsetorg = (byteoffset + falignorg-1) & ~(falignorg-1);
-            byteoffset = (byteoffset + falign-1) & ~(falign-1);
-
-            if (byteoffsetorg != byteoffset) {
-                ct->ct_flags |= CT_WITH_PACKED_CHANGE;
-            }
-
-            if (foffset >= 0) {
-                /* a forced field position: ignore the offset just computed,
-                   except to know if we must set CT_CUSTOM_FIELD_POS */
-                if (detect_custom_layout(ct, sflags, byteoffset, foffset,
-                                         "wrong offset for field '",
-                                         PyText_AS_UTF8(fname), "'") < 0)
-                    goto error;
-                byteoffset = foffset;
-            }
-
-            if (PyText_GetSize(fname) == 0 &&
-                    ftype->ct_flags & (CT_STRUCT|CT_UNION)) {
-                /* a nested anonymous struct or union */
-                CFieldObject *cfsrc = (CFieldObject *)ftype->ct_extra;
-                for (; cfsrc != NULL; cfsrc = cfsrc->cf_next) {
-                    /* broken complexity in the call to get_field_name(),
-                       but we'll assume you never do that with nested
-                       anonymous structures with thousand of fields */
-                    *previous = _add_field(interned_fields,
-                                           get_field_name(ftype, cfsrc),
-                                           cfsrc->cf_type,
-                                           byteoffset + cfsrc->cf_offset,
-                                           cfsrc->cf_bitshift,
-                                           cfsrc->cf_bitsize,
-                                           cfsrc->cf_flags | fflags);
-                    if (*previous == NULL)
-                        goto error;
-                    previous = &(*previous)->cf_next;
-                }
-                /* always forbid such structures from being passed by value */
-                ct->ct_flags |= CT_CUSTOM_FIELD_POS;
-            }
-            else {
-                *previous = _add_field(interned_fields, fname, ftype,
-                                       byteoffset, bs_flag, -1, fflags);
-                if (*previous == NULL)
-                    goto error;
-                previous = &(*previous)->cf_next;
-            }
-            if (ftype->ct_size >= 0)
-                byteoffset += ftype->ct_size;
-            prev_bitfield_size = 0;
-        }
-        else {
-            /* this is the case of a bitfield */
-            Py_ssize_t field_offset_bytes;
-            int bits_already_occupied, bitshift;
-
-            if (foffset >= 0) {
-                PyErr_Format(PyExc_TypeError,
-                             "field '%s.%s' is a bitfield, "
-                             "but a fixed offset is specified",
-                             ct->ct_name, PyText_AS_UTF8(fname));
-                goto error;
-            }
-
-            if (!(ftype->ct_flags & (CT_PRIMITIVE_SIGNED |
-                                     CT_PRIMITIVE_UNSIGNED |
-                                     CT_PRIMITIVE_CHAR))) {
-                PyErr_Format(PyExc_TypeError,
-                        "field '%s.%s' declared as '%s' cannot be a bit field",
-                             ct->ct_name, PyText_AS_UTF8(fname),
-                             ftype->ct_name);
-                goto error;
-            }
-            if (fbitsize > 8 * ftype->ct_size) {
-                PyErr_Format(PyExc_TypeError,
-                             "bit field '%s.%s' is declared '%s:%d', which "
-                             "exceeds the width of the type",
-                             ct->ct_name, PyText_AS_UTF8(fname),
-                             ftype->ct_name, fbitsize);
-                goto error;
-            }
-
-            /* compute the starting position of the theoretical field
-               that covers a complete 'ftype', inside of which we will
-               locate the real bitfield */
-            field_offset_bytes = byteoffset;
-            field_offset_bytes &= ~(falign - 1);
-
-            if (fbitsize == 0) {
-                if (PyText_GetSize(fname) > 0) {
-                    PyErr_Format(PyExc_TypeError,
-                                 "field '%s.%s' is declared with :0",
-                                 ct->ct_name, PyText_AS_UTF8(fname));
-                    goto error;
-                }
-                if (!(sflags & SF_MSVC_BITFIELDS)) {
-                    /* GCC's notion of "ftype :0;" */
-
-                    /* pad byteoffset to a value aligned for "ftype" */
-                    if (ROUNDUP_BYTES(byteoffset, bitoffset) > field_offset_bytes) {
-                        field_offset_bytes += falign;
-                        assert(byteoffset < field_offset_bytes);
-                    }
-                    byteoffset = field_offset_bytes;
-                    bitoffset = 0;
-                }
-                else {
-                    /* MSVC's notion of "ftype :0;" */
-
-                    /* Mostly ignored.  It seems they only serve as
-                       separator between other bitfields, to force them
-                       into separate words. */
-                }
-                prev_bitfield_size = 0;
-            }
-            else {
-                if (!(sflags & SF_MSVC_BITFIELDS)) {
-                    /* GCC's algorithm */
-
-                    /* Can the field start at the offset given by 'boffset'?  It
-                       can if it would entirely fit into an aligned ftype field. */
-                    bits_already_occupied = (byteoffset-field_offset_bytes) * 8
-                        + bitoffset;
-
-                    if (bits_already_occupied + fbitsize > 8 * ftype->ct_size) {
-                        /* it would not fit, we need to start at the next
-                           allowed position */
-                        if ((sflags & SF_PACKED) &&
-                            (bits_already_occupied & 7)) {
-                            PyErr_Format(PyExc_NotImplementedError,
-                                "with 'packed', gcc would compile field "
-                                "'%s.%s' to reuse some bits in the previous "
-                                "field", ct->ct_name, PyText_AS_UTF8(fname));
-                            goto error;
-                        }
-                        field_offset_bytes += falign;
-                        assert(byteoffset < field_offset_bytes);
-                        byteoffset = field_offset_bytes;
-                        bitoffset = 0;
-                        bitshift = 0;
-                    }
-                    else {
-                        bitshift = bits_already_occupied;
-                        assert(bitshift >= 0);
-                    }
-                    bitoffset += fbitsize;
-                    byteoffset += (bitoffset >> 3);
-                    bitoffset &= 7;
-                }
-                else {
-                    /* MSVC's algorithm */
-
-                    /* A bitfield is considered as taking the full width
-                       of their declared type.  It can share some bits
-                       with the previous field only if it was also a
-                       bitfield and used a type of the same size. */
-                    if (prev_bitfield_size == ftype->ct_size &&
-                        prev_bitfield_free >= fbitsize) {
-                        /* yes: reuse */
-                        bitshift = 8 * prev_bitfield_size - prev_bitfield_free;
-                    }
-                    else {
-                        /* no: start a new full field */
-                        byteoffset = ROUNDUP_BYTES(byteoffset, bitoffset);
-                        bitoffset = 0;
-                        /* align */
-                        byteoffset = (byteoffset + falign-1) & ~(falign-1);
-                        byteoffset += ftype->ct_size;
-                        bitshift = 0;
-                        prev_bitfield_size = ftype->ct_size;
-                        prev_bitfield_free = 8 * prev_bitfield_size;
-                    }
-                    prev_bitfield_free -= fbitsize;
-                    field_offset_bytes = byteoffset - ftype->ct_size;
-                }
-                if (sflags & SF_GCC_BIG_ENDIAN)
-                    bitshift = 8 * ftype->ct_size - fbitsize - bitshift;
-
-                if (PyText_GetSize(fname) > 0) {
-
-                    *previous = _add_field(interned_fields, fname, ftype,
-                                       field_offset_bytes, bitshift, fbitsize,
-                                       fflags);
-                    if (*previous == NULL)
-                        goto error;
-                    previous = &(*previous)->cf_next;
-                }
-            }
-        }
-
-        assert(bitoffset == (bitoffset & 7));
-        if (ROUNDUP_BYTES(byteoffset, bitoffset) > byteoffsetmax)
-            byteoffsetmax = ROUNDUP_BYTES(byteoffset, bitoffset);
-    }
-    *previous = NULL;
-
-    /* Like C, if the size of this structure would be zero, we compute it
-       as 1 instead.  But for ctypes support, we allow the manually-
-       specified totalsize to be zero in this case. */
-    alignedsize = (byteoffsetmax + alignment - 1) & ~(alignment-1);
-    if (alignedsize == 0)
-        alignedsize = 1;
-
-    if (totalsize < 0) {
-        totalsize = alignedsize;
-    }
-    else {
-        if (detect_custom_layout(ct, sflags, alignedsize,
-                                 totalsize, "wrong total size", "", "") < 0)
-            goto error;
-        if (totalsize < byteoffsetmax) {
-            PyErr_Format(PyExc_TypeError,
-                         "%s cannot be of size %zd: there are fields at least "
-                         "up to %zd", ct->ct_name, totalsize, byteoffsetmax);
-            goto error;
-        }
-    }
-    if (totalalignment < 0) {
-        totalalignment = alignment;
-    }
-    else {
-        if (detect_custom_layout(ct, sflags, alignment, totalalignment,
-                                 "wrong total alignment", "", "") < 0)
-            goto error;
-    }
-
-    ct->ct_size = totalsize;
-    ct->ct_length = totalalignment;
-    ct->ct_stuff = interned_fields;
-    ct->ct_flags &= ~CT_IS_OPAQUE;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-
- error:
-    ct->ct_extra = NULL;
-    Py_DECREF(interned_fields);
-    return NULL;
-}
-
-struct funcbuilder_s {
-    Py_ssize_t nb_bytes;
-    char *bufferp;
-    ffi_type **atypes;
-    ffi_type *rtype;
-    Py_ssize_t nargs;
-    CTypeDescrObject *fct;
-};
-
-static void *fb_alloc(struct funcbuilder_s *fb, Py_ssize_t size)
-{
-    if (fb->bufferp == NULL) {
-        fb->nb_bytes += size;
-        return NULL;
-    }
-    else {
-        char *result = fb->bufferp;
-        fb->bufferp += size;
-        return result;
-    }
-}
-
-#define SUPPORTED_IN_API_MODE                                            \
-        " are only supported as %s if the function is "                  \
-        "'API mode' and non-variadic (i.e. declared inside ffibuilder"   \
-        ".cdef()+ffibuilder.set_source() and not taking a final '...' "  \
-        "argument)"
-
-static ffi_type *fb_unsupported(CTypeDescrObject *ct, const char *place,
-                                const char *detail)
-{
-    PyErr_Format(PyExc_NotImplementedError,
-        "ctype '%s' not supported as %s.  %s.  "
-        "Such structs" SUPPORTED_IN_API_MODE,
-        ct->ct_name, place, detail, place);
-    return NULL;
-}
-
-static ffi_type *fb_fill_type(struct funcbuilder_s *fb, CTypeDescrObject *ct,
-                              int is_result_type)
-{
-    const char *place = is_result_type ? "return value" : "argument";
-
-    if (ct->ct_flags & (CT_PRIMITIVE_ANY & ~CT_PRIMITIVE_COMPLEX)) {
-        return (ffi_type *)ct->ct_extra;
-    }
-    else if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR)) {
-        return &ffi_type_pointer;
-    }
-    else if ((ct->ct_flags & CT_VOID) && is_result_type) {
-        return &ffi_type_void;
-    }
-
-    if (ct->ct_size <= 0) {
-        PyErr_Format(PyExc_TypeError,
-                     ct->ct_size < 0 ? "ctype '%s' has incomplete type"
-                                     : "ctype '%s' has size 0",
-                     ct->ct_name);
-        return NULL;
-    }
-    if (ct->ct_flags & CT_STRUCT) {
-        ffi_type *ffistruct, *ffifield;
-        ffi_type **elements;
-        Py_ssize_t i, n, nflat;
-        CFieldObject *cf;
-
-        /* We can't pass a struct that was completed by verify().
-           Issue: assume verify() is given "struct { long b; ...; }".
-           Then it will complete it in the same way whether it is actually
-           "struct { long a, b; }" or "struct { double a; long b; }".
-           But on 64-bit UNIX, these two structs are passed by value
-           differently: e.g. on x86-64, "b" ends up in register "rsi" in
-           the first case and "rdi" in the second case.
-
-           Another reason for CT_CUSTOM_FIELD_POS would be anonymous
-           nested structures: we lost the information about having it
-           here, so better safe (and forbid it) than sorry (and maybe
-           crash).  Note: it seems we only get in this case with
-           ffi.verify().
-        */
-        if (force_lazy_struct(ct) < 0)
-            return NULL;
-        if (ct->ct_flags & CT_CUSTOM_FIELD_POS) {
-            /* these NotImplementedErrors may be caught and ignored until
-               a real call is made to a function of this type */
-            return fb_unsupported(ct, place,
-                "It is a struct declared with \"...;\", but the C "
-                "calling convention may depend on the missing fields; "
-                "or, it contains anonymous struct/unions");
-        }
-        /* Another reason: __attribute__((packed)) is not supported by libffi.
-        */
-        if (ct->ct_flags & CT_WITH_PACKED_CHANGE) {
-            return fb_unsupported(ct, place,
-                "It is a 'packed' structure, with a different layout than "
-                "expected by libffi");
-        }
-
-        n = PyDict_Size(ct->ct_stuff);
-        nflat = 0;
-
-        /* walk the fields, expanding arrays into repetitions; first,
-           only count how many flattened fields there are */
-        cf = (CFieldObject *)ct->ct_extra;
-        for (i=0; i<n; i++) {
-            Py_ssize_t flat;
-            CTypeDescrObject *ct1;
-            assert(cf != NULL);
-            if (cf->cf_bitshift >= 0) {
-                return fb_unsupported(ct, place,
-                    "It is a struct with bit fields, which libffi does not "
-                    "support");
-            }
-            flat = 1;
-            ct1 = cf->cf_type;
-            while (ct1->ct_flags & CT_ARRAY) {
-                flat *= ct1->ct_length;
-                ct1 = ct1->ct_itemdescr;
-            }
-            if (flat <= 0) {
-                return fb_unsupported(ct, place,
-                    "It is a struct with a zero-length array, which libffi "
-                    "does not support");
-            }
-            nflat += flat;
-            cf = cf->cf_next;
-        }
-        assert(cf == NULL);
-
-        /* next, allocate and fill the flattened list */
-        elements = fb_alloc(fb, (nflat + 1) * sizeof(ffi_type*));
-        nflat = 0;
-        cf = (CFieldObject *)ct->ct_extra;
-        for (i=0; i<n; i++) {
-            Py_ssize_t j, flat = 1;
-            CTypeDescrObject *ct = cf->cf_type;
-            while (ct->ct_flags & CT_ARRAY) {
-                flat *= ct->ct_length;
-                ct = ct->ct_itemdescr;
-            }
-            ffifield = fb_fill_type(fb, ct, 0);
-            if (PyErr_Occurred())
-                return NULL;
-            if (elements != NULL) {
-                for (j=0; j<flat; j++)
-                    elements[nflat++] = ffifield;
-            }
-            cf = cf->cf_next;
-        }
-
-        /* finally, allocate the FFI_TYPE_STRUCT */
-        ffistruct = fb_alloc(fb, sizeof(ffi_type));
-        if (ffistruct != NULL) {
-            elements[nflat] = NULL;
-            ffistruct->size = ct->ct_size;
-            ffistruct->alignment = ct->ct_length;
-            ffistruct->type = FFI_TYPE_STRUCT;
-            ffistruct->elements = elements;
-        }
-        return ffistruct;
-    }
-    else if (ct->ct_flags & CT_UNION) {
-        PyErr_Format(PyExc_NotImplementedError,
-                     "ctype '%s' not supported as %s by libffi.  "
-                     "Unions" SUPPORTED_IN_API_MODE,
-                     ct->ct_name, place, place);
-        return NULL;
-    }
-    else {
-        char *extra = "";
-        if (ct->ct_flags & CT_PRIMITIVE_COMPLEX)
-            extra = " (the support for complex types inside libffi "
-                    "is mostly missing at this point, so CFFI only "
-                    "supports complex types as arguments or return "
-                    "value in API-mode functions)";
-
-        PyErr_Format(PyExc_NotImplementedError,
-                     "ctype '%s' (size %zd) not supported as %s%s",
-                     ct->ct_name, ct->ct_size, place, extra);
-        return NULL;
-    }
-}
-
-#define ALIGN_ARG(n)  ((n) + 7) & ~7
-
-static int fb_build(struct funcbuilder_s *fb, PyObject *fargs,
-                    CTypeDescrObject *fresult)
-{
-    Py_ssize_t i, nargs = PyTuple_GET_SIZE(fargs);
-    Py_ssize_t exchange_offset;
-    cif_description_t *cif_descr;
-
-    /* ffi buffer: start with a cif_description */
-    cif_descr = fb_alloc(fb, sizeof(cif_description_t) +
-                             nargs * sizeof(Py_ssize_t));
-
-    /* ffi buffer: next comes an array of 'ffi_type*', one per argument */
-    fb->atypes = fb_alloc(fb, nargs * sizeof(ffi_type*));
-    fb->nargs = nargs;
-
-    /* ffi buffer: next comes the result type */
-    fb->rtype = fb_fill_type(fb, fresult, 1);
-    if (PyErr_Occurred())
-        return -1;
-    if (cif_descr != NULL) {
-        /* exchange data size */
-        /* first, enough room for an array of 'nargs' pointers */
-        exchange_offset = nargs * sizeof(void*);
-        exchange_offset = ALIGN_ARG(exchange_offset);
-        cif_descr->exchange_offset_arg[0] = exchange_offset;
-        /* then enough room for the result --- which means at least
-           sizeof(ffi_arg), according to the ffi docs */
-        i = fb->rtype->size;
-        if (i < (Py_ssize_t)sizeof(ffi_arg))
-            i = sizeof(ffi_arg);
-        exchange_offset += i;
-    }
-    else
-        exchange_offset = 0;   /* not used */
-
-    /* loop over the arguments */
-    for (i=0; i<nargs; i++) {
-        CTypeDescrObject *farg;
-        ffi_type *atype;
-
-        farg = (CTypeDescrObject *)PyTuple_GET_ITEM(fargs, i);
-        /* convert arrays to pointers */
-        if (farg->ct_flags & CT_ARRAY)
-            farg = (CTypeDescrObject *)farg->ct_stuff;
-
-        /* ffi buffer: fill in the ffi for the i'th argument */
-        assert(farg != NULL);
-        atype = fb_fill_type(fb, farg, 0);
-        if (PyErr_Occurred())
-            return -1;
-
-        if (fb->atypes != NULL) {
-            fb->atypes[i] = atype;
-            /* exchange data size */
-            exchange_offset = ALIGN_ARG(exchange_offset);
-            cif_descr->exchange_offset_arg[1 + i] = exchange_offset;
-            exchange_offset += atype->size;
-        }
-    }
-
-    if (cif_descr != NULL) {
-        /* exchange data size */
-        /* we also align it to the next multiple of 8, in an attempt to
-           work around bugs(?) of libffi like #241 */
-        cif_descr->exchange_size = ALIGN_ARG(exchange_offset);
-    }
-    return 0;
-}
-
-#undef ALIGN_ARG
-
-static void fb_cat_name(struct funcbuilder_s *fb, const char *piece,
-                        int piecelen)
-{
-    if (fb->bufferp == NULL) {
-        fb->nb_bytes += piecelen;
-    }
-    else {
-        memcpy(fb->bufferp, piece, piecelen);
-        fb->bufferp += piecelen;
-    }
-}
-
-static int fb_build_name(struct funcbuilder_s *fb, const char *repl,
-                         CTypeDescrObject **pfargs, Py_ssize_t nargs,
-                         CTypeDescrObject *fresult, int ellipsis)
-{
-    Py_ssize_t i;
-    fb->nargs = nargs;
-
-    /* name: the function type name we build here is, like in C, made
-       as follows:
-
-         RESULT_TYPE_HEAD (*)(ARG_1_TYPE, ARG_2_TYPE, etc) RESULT_TYPE_TAIL
-    */
-    fb_cat_name(fb, fresult->ct_name, fresult->ct_name_position);
-    if (repl[0] != '(' &&
-        fresult->ct_name[fresult->ct_name_position - 1] != '*')
-        fb_cat_name(fb, " ", 1);   /* add a space */
-    fb_cat_name(fb, repl, strlen(repl));
-    if (fb->fct) {
-        i = strlen(repl) - 1;      /* between '(*' and ')' */
-        assert(repl[i] == ')');
-        fb->fct->ct_name_position = fresult->ct_name_position + i;
-    }
-    fb_cat_name(fb, "(", 1);
-
-    /* loop over the arguments */
-    for (i=0; i<nargs; i++) {
-        CTypeDescrObject *farg;
-
-        farg = pfargs[i];
-        if (!CTypeDescr_Check(farg)) {
-            PyErr_SetString(PyExc_TypeError, "expected a tuple of ctypes");
-            return -1;
-        }
-        /* name: concatenate the name of the i'th argument's type */
-        if (i > 0)
-            fb_cat_name(fb, ", ", 2);
-        fb_cat_name(fb, farg->ct_name, strlen(farg->ct_name));
-    }
-
-    /* name: add the '...' if needed */
-    if (ellipsis) {
-        if (nargs > 0)
-            fb_cat_name(fb, ", ", 2);
-        fb_cat_name(fb, "...", 3);
-    }
-
-    /* name: concatenate the tail of the result type */
-    fb_cat_name(fb, ")", 1);
-    fb_cat_name(fb, fresult->ct_name + fresult->ct_name_position,
-                strlen(fresult->ct_name) - fresult->ct_name_position + 1);
-    return 0;
-}
-
-static CTypeDescrObject *fb_prepare_ctype(struct funcbuilder_s *fb,
-                                          PyObject *fargs,
-                                          CTypeDescrObject *fresult,
-                                          int ellipsis, int fabi)
-{
-    CTypeDescrObject *fct, **pfargs;
-    Py_ssize_t nargs;
-    char *repl = "(*)";
-
-    fb->nb_bytes = 0;
-    fb->bufferp = NULL;
-    fb->fct = NULL;
-
-    pfargs = (CTypeDescrObject **)&PyTuple_GET_ITEM(fargs, 0);
-    nargs = PyTuple_GET_SIZE(fargs);
-#if defined(MS_WIN32) && !defined(_WIN64)
-    if (fabi == FFI_STDCALL)
-        repl = "(__stdcall *)";
-#endif
-
-    /* compute the total size needed for the name */
-    if (fb_build_name(fb, repl, pfargs, nargs, fresult, ellipsis) < 0)
-        return NULL;
-
-    /* allocate the function type */
-    fct = ctypedescr_new(fb->nb_bytes);
-    if (fct == NULL)
-        return NULL;
-    fb->fct = fct;
-
-    /* call again fb_build_name() to really build the ct_name */
-    fb->bufferp = fct->ct_name;
-    if (fb_build_name(fb, repl, pfargs, nargs, fresult, ellipsis) < 0)
-        goto error;
-    assert(fb->bufferp == fct->ct_name + fb->nb_bytes);
-
-    fct->ct_extra = NULL;
-    fct->ct_size = sizeof(void(*)(void));
-    fct->ct_flags = CT_FUNCTIONPTR;
-    return fct;
-
- error:
-    Py_DECREF(fct);
-    return NULL;
-}
-
-static cif_description_t *fb_prepare_cif(PyObject *fargs,
-                                         CTypeDescrObject *fresult,
-                                         Py_ssize_t variadic_nargs_declared,
-                                         ffi_abi fabi)
-
-{
-    char *buffer;
-    cif_description_t *cif_descr;
-    struct funcbuilder_s funcbuffer;
-    ffi_status status = (ffi_status)-1;
-
-    funcbuffer.nb_bytes = 0;
-    funcbuffer.bufferp = NULL;
-
-    /* compute the total size needed in the buffer for libffi */
-    if (fb_build(&funcbuffer, fargs, fresult) < 0)
-        return NULL;
-
-    /* allocate the buffer */
-    buffer = PyObject_Malloc(funcbuffer.nb_bytes);
-    if (buffer == NULL) {
-        PyErr_NoMemory();
-        return NULL;
-    }
-
-    /* call again fb_build() to really build the libffi data structures */
-    funcbuffer.bufferp = buffer;
-    if (fb_build(&funcbuffer, fargs, fresult) < 0)
-        goto error;
-    assert(funcbuffer.bufferp == buffer + funcbuffer.nb_bytes);
-
-    cif_descr = (cif_description_t *)buffer;
-
-    /* use `ffi_prep_cif_var` if necessary and available */
-#if CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE
-    if (variadic_nargs_declared >= 0) {
-        if (CFFI_CHECK_FFI_PREP_CIF_VAR) {
-            status = ffi_prep_cif_var(&cif_descr->cif, fabi,
-                                      variadic_nargs_declared, funcbuffer.nargs,
-                                      funcbuffer.rtype, funcbuffer.atypes);
-        }
-    }
-#endif
-
-    if (status == (ffi_status)-1) {
-        status = ffi_prep_cif(&cif_descr->cif, fabi, funcbuffer.nargs,
-                              funcbuffer.rtype, funcbuffer.atypes);
-    }
-
-    if (status != FFI_OK) {
-        PyErr_SetString(PyExc_SystemError,
-                        "libffi failed to build this function type");
-        goto error;
-    }
-    return cif_descr;
-
- error:
-    PyObject_Free(buffer);
-    return NULL;
-}
-
-static PyObject *new_function_type(PyObject *fargs,   /* tuple */
-                                   CTypeDescrObject *fresult,
-                                   int ellipsis, int fabi)
-{
-    PyObject *fabiobj;
-    CTypeDescrObject *fct;
-    struct funcbuilder_s funcbuilder;
-    Py_ssize_t i;
-    const void **unique_key;
-
-    if ((fresult->ct_size < 0 && !(fresult->ct_flags & CT_VOID)) ||
-        (fresult->ct_flags & CT_ARRAY)) {
-        char *msg;
-        if (fresult->ct_flags & CT_IS_OPAQUE)
-            msg = "result type '%s' is opaque";
-        else
-            msg = "invalid result type: '%s'";
-        PyErr_Format(PyExc_TypeError, msg, fresult->ct_name);
-        return NULL;
-    }
-
-    fct = fb_prepare_ctype(&funcbuilder, fargs, fresult, ellipsis, fabi);
-    if (fct == NULL)
-        return NULL;
-
-    if (!ellipsis) {
-        /* Functions with '...' varargs are stored without a cif_descr
-           at all.  The cif is computed on every call from the actual
-           types passed in.  For all other functions, the cif_descr
-           is computed here. */
-        cif_description_t *cif_descr;
-
-        cif_descr = fb_prepare_cif(fargs, fresult, -1, fabi);
-        if (cif_descr == NULL) {
-            if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
-                PyErr_Clear();   /* will get the exception if we see an
-                                    actual call */
-            }
-            else
-                goto error;
-        }
-
-        fct->ct_extra = (char *)cif_descr;
-    }
-
-    /* build the signature, given by a tuple of ctype objects */
-    fct->ct_stuff = PyTuple_New(2 + funcbuilder.nargs);
-    if (fct->ct_stuff == NULL)
-        goto error;
-    fabiobj = PyInt_FromLong(fabi);
-    if (fabiobj == NULL)
-        goto error;
-    PyTuple_SET_ITEM(fct->ct_stuff, 0, fabiobj);
-
-    Py_INCREF(fresult);
-    PyTuple_SET_ITEM(fct->ct_stuff, 1, (PyObject *)fresult);
-    for (i=0; i<funcbuilder.nargs; i++) {
-        PyObject *o = PyTuple_GET_ITEM(fargs, i);
-        /* convert arrays into pointers */
-        if (((CTypeDescrObject *)o)->ct_flags & CT_ARRAY)
-            o = ((CTypeDescrObject *)o)->ct_stuff;
-        Py_INCREF(o);
-        PyTuple_SET_ITEM(fct->ct_stuff, 2 + i, o);
-    }
-
-    /* [ctresult, ellipsis+abi, num_args, ctargs...] */
-    unique_key = alloca((3 + funcbuilder.nargs) * sizeof(void *));
-    unique_key[0] = fresult;
-    unique_key[1] = (const void *)(Py_ssize_t)((fabi << 1) | !!ellipsis);
-    unique_key[2] = (const void *)(Py_ssize_t)(funcbuilder.nargs);
-    for (i=0; i<funcbuilder.nargs; i++)
-        unique_key[3 + i] = PyTuple_GET_ITEM(fct->ct_stuff, 2 + i);
-    return get_unique_type(fct, unique_key, 3 + funcbuilder.nargs);
-
- error:
-    Py_DECREF(fct);
-    return NULL;
-}
-
-static PyObject *b_new_function_type(PyObject *self, PyObject *args)
-{
-    PyObject *fargs;
-    CTypeDescrObject *fresult;
-    int ellipsis = 0, fabi = FFI_DEFAULT_ABI;
-
-    if (!PyArg_ParseTuple(args, "O!O!|ii:new_function_type",
-                          &PyTuple_Type, &fargs,
-                          &CTypeDescr_Type, &fresult,
-                          &ellipsis,
-                          &fabi))
-        return NULL;
-
-    return new_function_type(fargs, fresult, ellipsis, fabi);
-}
-
-static int convert_from_object_fficallback(char *result,
-                                           CTypeDescrObject *ctype,
-                                           PyObject *pyobj,
-                                           int encode_result_for_libffi)
-{
-    /* work work work around a libffi irregularity: for integer return
-       types we have to fill at least a complete 'ffi_arg'-sized result
-       buffer. */
-    if (ctype->ct_size < (Py_ssize_t)sizeof(ffi_arg)) {
-        if (ctype->ct_flags & CT_VOID) {
-            if (pyobj == Py_None) {
-                return 0;
-            }
-            else {
-                PyErr_SetString(PyExc_TypeError,
-                    "callback with the return type 'void' must return None");
-                return -1;
-            }
-        }
-        if (!encode_result_for_libffi)
-            goto skip;
-        if (ctype->ct_flags & CT_PRIMITIVE_SIGNED) {
-            PY_LONG_LONG value;
-            /* It's probably fine to always zero-extend, but you never
-               know: maybe some code somewhere expects a negative
-               'short' result to be returned into EAX as a 32-bit
-               negative number.  Better safe than sorry.  This code
-               is about that case.  Let's ignore this for enums.
-            */
-            /* do a first conversion only to detect overflows.  This
-               conversion produces stuff that is otherwise ignored. */
-            if (convert_from_object(result, ctype, pyobj) < 0)
-                return -1;
-            /* manual inlining and tweaking of convert_from_object()
-               in order to write a whole 'ffi_arg'. */
-            value = _my_PyLong_AsLongLong(pyobj);
-            if (value == -1 && PyErr_Occurred())
-                return -1;
-            write_raw_integer_data(result, value, sizeof(ffi_arg));
-            return 0;
-        }
-        else if (ctype->ct_flags & (CT_PRIMITIVE_CHAR | CT_PRIMITIVE_SIGNED |
-                                    CT_PRIMITIVE_UNSIGNED |
-                                    CT_POINTER | CT_FUNCTIONPTR)) {
-            /* zero extension: fill the '*result' with zeros, and (on big-
-               endian machines) correct the 'result' pointer to write to.
-               We also do that for pointers, even though we're normally not
-               in this branch because ctype->ct_size == sizeof(ffi_arg) for
-               pointers---except on some architectures like x32 (issue #372).
-             */
-            memset(result, 0, sizeof(ffi_arg));
-#ifdef WORDS_BIGENDIAN
-            result += (sizeof(ffi_arg) - ctype->ct_size);
-#endif
-        }
-    }
- skip:
-    return convert_from_object(result, ctype, pyobj);
-}
-
-static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb,
-                                      char *objdescr, PyObject *obj,
-                                      char *extra_error_line)
-{
-    /* like PyErr_WriteUnraisable(), but write a full traceback */
-#ifdef USE_WRITEUNRAISABLEMSG
-
-    /* PyErr_WriteUnraisable actually writes the full traceback anyway
-       from Python 3.4, but we can't really get the formatting of the
-       custom text to be what we want.  We can do better from Python
-       3.8 by calling the new _PyErr_WriteUnraisableMsg().
-       Luckily it's also Python 3.8 that adds new functionality that
-       people might want: the new sys.unraisablehook().
-    */
-    PyObject *s;
-    int first_char;
-    assert(objdescr != NULL && objdescr[0] != 0);   /* non-empty */
-    first_char = objdescr[0];
-    if (first_char >= 'A' && first_char <= 'Z')
-        first_char += 'a' - 'A';    /* lower() the very first character */
-    if (extra_error_line == NULL)
-        extra_error_line = "";
-
-    if (obj != NULL)
-        s = PyUnicode_FromFormat("%c%s%R%s",
-            first_char, objdescr + 1, obj, extra_error_line);
-    else
-        s = PyUnicode_FromFormat("%c%s%s",
-            first_char, objdescr + 1, extra_error_line);
-
-    PyErr_Restore(t, v, tb);
-    if (s != NULL) {
-        _PyErr_WriteUnraisableMsg(PyText_AS_UTF8(s), NULL);
-        Py_DECREF(s);
-    }
-    else
-        PyErr_WriteUnraisable(obj);   /* best effort */
-    PyErr_Clear();
-
-#else
-
-    /* version for Python 2.7 and < 3.8 */
-    PyObject *f;
-#if PY_MAJOR_VERSION >= 3
-    /* jump through hoops to ensure the tb is attached to v, on Python 3 */
-    PyErr_NormalizeException(&t, &v, &tb);
-    if (tb == NULL) {
-        tb = Py_None;
-        Py_INCREF(tb);
-    }
-    PyException_SetTraceback(v, tb);
-#endif
-    f = PySys_GetObject("stderr");
-    if (f != NULL) {
-        if (obj != NULL) {
-            PyFile_WriteString(objdescr, f);
-            PyFile_WriteObject(obj, f, 0);
-            PyFile_WriteString(":\n", f);
-        }
-        if (extra_error_line != NULL)
-            PyFile_WriteString(extra_error_line, f);
-        PyErr_Display(t, v, tb);
-    }
-    Py_XDECREF(t);
-    Py_XDECREF(v);
-    Py_XDECREF(tb);
-
-#endif
-}
-
-static void general_invoke_callback(int decode_args_from_libffi,
-                                    void *result, char *args, void *userdata)
-{
-    PyObject *cb_args = (PyObject *)userdata;
-    CTypeDescrObject *ct = (CTypeDescrObject *)PyTuple_GET_ITEM(cb_args, 0);
-    PyObject *signature = ct->ct_stuff;
-    PyObject *py_ob = PyTuple_GET_ITEM(cb_args, 1);
-    PyObject *py_args = NULL;
-    PyObject *py_res = NULL;
-    PyObject *py_rawerr;
-    PyObject *onerror_cb;
-    Py_ssize_t i, n;
-    char *extra_error_line = NULL;
-
-#define SIGNATURE(i)  ((CTypeDescrObject *)PyTuple_GET_ITEM(signature, i))
-
-    Py_INCREF(cb_args);
-
-    n = PyTuple_GET_SIZE(signature) - 2;
-    py_args = PyTuple_New(n);
-    if (py_args == NULL)
-        goto error;
-
-    for (i=0; i<n; i++) {
-        char *a_src;
-        PyObject *a;
-        CTypeDescrObject *a_ct = SIGNATURE(2 + i);
-
-        if (decode_args_from_libffi) {
-            a_src = ((void **)args)[i];
-        }
-        else {
-            a_src = args + i * 8;
-            if (a_ct->ct_flags & (CT_IS_LONGDOUBLE | CT_STRUCT | CT_UNION))
-                a_src = *(char **)a_src;
-        }
-        a = convert_to_object(a_src, a_ct);
-        if (a == NULL)
-            goto error;
-        PyTuple_SET_ITEM(py_args, i, a);
-    }
-
-    py_res = PyObject_Call(py_ob, py_args, NULL);
-    if (py_res == NULL)
-        goto error;
-    if (convert_from_object_fficallback(result, SIGNATURE(1), py_res,
-                                        decode_args_from_libffi) < 0) {
-#ifdef USE_WRITEUNRAISABLEMSG
-        extra_error_line = ", trying to convert the result back to C";
-#else
-        extra_error_line = "Trying to convert the result back to C:\n";
-#endif
-        goto error;
-    }
- done:
-    Py_XDECREF(py_args);
-    Py_XDECREF(py_res);
-    Py_DECREF(cb_args);
-    return;
-
- error:
-    if (SIGNATURE(1)->ct_size > 0) {
-        py_rawerr = PyTuple_GET_ITEM(cb_args, 2);
-        memcpy(result, PyBytes_AS_STRING(py_rawerr),
-                       PyBytes_GET_SIZE(py_rawerr));
-    }
-    onerror_cb = PyTuple_GET_ITEM(cb_args, 3);
-    if (onerror_cb == Py_None) {
-        PyObject *ecap, *t, *v, *tb;
-        PyErr_Fetch(&t, &v, &tb);
-        ecap = _cffi_start_error_capture();
-        _my_PyErr_WriteUnraisable(t, v, tb, "From cffi callback ", py_ob,
-                                  extra_error_line);
-        _cffi_stop_error_capture(ecap);
-    }
-    else {
-        PyObject *exc1, *val1, *tb1, *res1, *exc2, *val2, *tb2;
-        PyErr_Fetch(&exc1, &val1, &tb1);
-        PyErr_NormalizeException(&exc1, &val1, &tb1);
-        res1 = PyObject_CallFunctionObjArgs(onerror_cb,
-                                            exc1 ? exc1 : Py_None,
-                                            val1 ? val1 : Py_None,
-                                            tb1  ? tb1  : Py_None,
-                                            NULL);
-        if (res1 != NULL) {
-            if (res1 != Py_None)
-                convert_from_object_fficallback(result, SIGNATURE(1), res1,
-                                                decode_args_from_libffi);
-            Py_DECREF(res1);
-        }
-        if (!PyErr_Occurred()) {
-            Py_XDECREF(exc1);
-            Py_XDECREF(val1);
-            Py_XDECREF(tb1);
-        }
-        else {
-            /* double exception! print a double-traceback... */
-            PyObject *ecap;
-            PyErr_Fetch(&exc2, &val2, &tb2);
-            ecap = _cffi_start_error_capture();
-            _my_PyErr_WriteUnraisable(exc1, val1, tb1,
-                                      "From cffi callback ", py_ob,
-                                      extra_error_line);
-#ifdef USE_WRITEUNRAISABLEMSG
-            _my_PyErr_WriteUnraisable(exc2, val2, tb2,
-                 "during handling of the above exception by 'onerror'",
-                 NULL, NULL);
-#else
-            extra_error_line = ("\nDuring the call to 'onerror', "
-                                "another exception occurred:\n\n");
-            _my_PyErr_WriteUnraisable(exc2, val2, tb2,
-                                      NULL, NULL, extra_error_line);
-#endif
-            _cffi_stop_error_capture(ecap);
-        }
-    }
-    goto done;
-
-#undef SIGNATURE
-}
-
-static void invoke_callback(ffi_cif *cif, void *result, void **args,
-                            void *userdata)
-{
-    save_errno();
-    {
-        PyGILState_STATE state = gil_ensure();
-        general_invoke_callback(1, result, (char *)args, userdata);
-        gil_release(state);
-    }
-    restore_errno();
-}
-
-static PyObject *prepare_callback_info_tuple(CTypeDescrObject *ct,
-                                             PyObject *ob,
-                                             PyObject *error_ob,
-                                             PyObject *onerror_ob,
-                                             int decode_args_from_libffi)
-{
-    CTypeDescrObject *ctresult;
-    PyObject *py_rawerr, *infotuple;
-    Py_ssize_t size;
-
-    if (!(ct->ct_flags & CT_FUNCTIONPTR)) {
-        PyErr_Format(PyExc_TypeError, "expected a function ctype, got '%s'",
-                     ct->ct_name);
-        return NULL;
-    }
-    if (!PyCallable_Check(ob)) {
-        PyErr_Format(PyExc_TypeError,
-                     "expected a callable object, not %.200s",
-                     Py_TYPE(ob)->tp_name);
-        return NULL;
-    }
-    if (onerror_ob != Py_None && !PyCallable_Check(onerror_ob)) {
-        PyErr_Format(PyExc_TypeError,
-                     "expected a callable object for 'onerror', not %.200s",
-                     Py_TYPE(onerror_ob)->tp_name);
-        return NULL;
-    }
-
-    ctresult = (CTypeDescrObject *)PyTuple_GET_ITEM(ct->ct_stuff, 1);
-    size = ctresult->ct_size;
-    if (size < (Py_ssize_t)sizeof(ffi_arg))
-        size = sizeof(ffi_arg);
-    py_rawerr = PyBytes_FromStringAndSize(NULL, size);
-    if (py_rawerr == NULL)
-        return NULL;
-    memset(PyBytes_AS_STRING(py_rawerr), 0, size);
-    if (error_ob != Py_None) {
-        if (convert_from_object_fficallback(
-                PyBytes_AS_STRING(py_rawerr), ctresult, error_ob,
-                decode_args_from_libffi) < 0) {
-            Py_DECREF(py_rawerr);
-            return NULL;
-        }
-    }
-    infotuple = Py_BuildValue("OOOO", ct, ob, py_rawerr, onerror_ob);
-    Py_DECREF(py_rawerr);
-
-#if defined(WITH_THREAD) && PY_VERSION_HEX < 0x03070000
-    /* We must setup the GIL here, in case the callback is invoked in
-       some other non-Pythonic thread.  This is the same as ctypes.
-       But PyEval_InitThreads() is always a no-op from CPython 3.7
-       (the call from ctypes was removed some time later I think). */
-    PyEval_InitThreads();
-#endif
-
-    return infotuple;
-}
-
-/* messily try to silence a gcc/clang deprecation warning for
-   ffi_prep_closure.  Don't miss the "pragma pop" after the function.
-   This is done around the whole function because very old GCCs don't
-   support it inside a function. */
-#if defined(__clang__)
-#  pragma clang diagnostic push
-#  pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#elif defined(__GNUC__)
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-static PyObject *b_callback(PyObject *self, PyObject *args)
-{
-    CTypeDescrObject *ct;
-    CDataObject_closure *cd;
-    PyObject *ob, *error_ob = Py_None, *onerror_ob = Py_None;
-    PyObject *infotuple;
-    cif_description_t *cif_descr;
-    ffi_closure *closure;
-    ffi_status status;
-    void *closure_exec;
-
-    if (!PyArg_ParseTuple(args, "O!O|OO:callback", &CTypeDescr_Type, &ct, &ob,
-                          &error_ob, &onerror_ob))
-        return NULL;
-
-    infotuple = prepare_callback_info_tuple(ct, ob, error_ob, onerror_ob, 1);
-    if (infotuple == NULL)
-        return NULL;
-
-#if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE
-    if (CFFI_CHECK_FFI_CLOSURE_ALLOC) {
-        closure = ffi_closure_alloc(sizeof(ffi_closure), &closure_exec);
-    } else
-#endif
-    {
-        closure = cffi_closure_alloc();
-        closure_exec = closure;
-    }
-
-    if (closure == NULL) {
-        Py_DECREF(infotuple);
-        PyErr_SetString(PyExc_MemoryError,
-            "Cannot allocate write+execute memory for ffi.callback(). "
-            "You might be running on a system that prevents this. "
-            "For more information, see "
-            "https://cffi.readthedocs.io/en/latest/using.html#callbacks");
-        return NULL;
-    }
-    cd = PyObject_GC_New(CDataObject_closure, &CDataOwningGC_Type);
-    if (cd == NULL)
-        goto error;
-    Py_INCREF(ct);
-    cd->head.c_type = ct;
-    cd->head.c_data = (char *)closure_exec;
-    cd->head.c_weakreflist = NULL;
-    closure->user_data = NULL;
-    cd->closure = closure;
-
-    cif_descr = (cif_description_t *)ct->ct_extra;
-    if (cif_descr == NULL) {
-        PyErr_Format(PyExc_NotImplementedError,
-                     "%s: callback with unsupported argument or "
-                     "return type or with '...'", ct->ct_name);
-        goto error;
-    }
-
-#if CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE
-    if (CFFI_CHECK_FFI_PREP_CLOSURE_LOC) {
-        status = ffi_prep_closure_loc(closure, &cif_descr->cif,
-                                      invoke_callback, infotuple, closure_exec);
-    }
-    else
-#endif
-    {
-#if defined(__APPLE__) && defined(FFI_AVAILABLE_APPLE) && !FFI_LEGACY_CLOSURE_API
-        PyErr_Format(PyExc_SystemError, "ffi_prep_closure_loc() is missing");
-        goto error;
-#else
-        status = ffi_prep_closure(closure, &cif_descr->cif,
-                                  invoke_callback, infotuple);
-#endif
-    }
-
-    if (status != FFI_OK) {
-        PyErr_SetString(PyExc_SystemError,
-                        "libffi failed to build this callback");
-        goto error;
-    }
-
-    if (closure->user_data != infotuple) {
-        /* Issue #266.  Should not occur, but could, if we are using
-           at runtime a version of libffi compiled with a different
-           'ffi_closure' structure than the one we expect from ffi.h
-           (e.g. difference in details of the platform): a difference
-           in FFI_TRAMPOLINE_SIZE means that the 'user_data' field
-           ends up somewhere else, and so the test above fails.
-        */
-        PyErr_SetString(PyExc_SystemError,
-            "ffi_prep_closure(): bad user_data (it seems that the "
-            "version of the libffi library seen at runtime is "
-            "different from the 'ffi.h' file seen at compile-time)");
-        goto error;
-    }
-    PyObject_GC_Track(cd);
-    return (PyObject *)cd;
-
- error:
-    closure->user_data = NULL;
-    if (cd == NULL) {
-#if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE
-        if (CFFI_CHECK_FFI_CLOSURE_ALLOC) {
-            ffi_closure_free(closure);
-        }
-        else
-#endif
-            cffi_closure_free(closure);
-    }
-    else
-        Py_DECREF(cd);
-    Py_XDECREF(infotuple);
-    return NULL;
-}
-#if defined(__clang__)
-#  pragma clang diagnostic pop
-#elif defined(__GNUC__)
-#  pragma GCC diagnostic pop
-#endif
-
-static PyObject *b_new_enum_type(PyObject *self, PyObject *args)
-{
-    char *ename;
-    PyObject *enumerators, *enumvalues;
-    PyObject *dict1 = NULL, *dict2 = NULL, *combined = NULL, *tmpkey = NULL;
-    int name_size;
-    CTypeDescrObject *td, *basetd;
-    Py_ssize_t i, n;
-
-    if (!PyArg_ParseTuple(args, "sO!O!O!:new_enum_type",
-                          &ename,
-                          &PyTuple_Type, &enumerators,
-                          &PyTuple_Type, &enumvalues,
-                          &CTypeDescr_Type, &basetd))
-        return NULL;
-
-    n = PyTuple_GET_SIZE(enumerators);
-    if (n != PyTuple_GET_SIZE(enumvalues)) {
-        PyErr_SetString(PyExc_ValueError,
-                        "tuple args must have the same size");
-        return NULL;
-    }
-
-    if (!(basetd->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED))) {
-        PyErr_SetString(PyExc_TypeError,
-                        "expected a primitive signed or unsigned base type");
-        return NULL;
-    }
-
-    dict1 = PyDict_New();
-    if (dict1 == NULL)
-        goto error;
-    dict2 = PyDict_New();
-    if (dict2 == NULL)
-        goto error;
-
-    for (i=n; --i >= 0; ) {
-        long long lvalue;
-        PyObject *value = PyTuple_GET_ITEM(enumvalues, i);
-        tmpkey = PyTuple_GET_ITEM(enumerators, i);
-        Py_INCREF(tmpkey);
-        if (!PyText_Check(tmpkey)) {
-#if PY_MAJOR_VERSION < 3
-            if (PyUnicode_Check(tmpkey)) {
-                const char *text = PyText_AsUTF8(tmpkey);
-                if (text == NULL)
-                    goto error;
-                Py_DECREF(tmpkey);
-                tmpkey = PyString_FromString(text);
-                if (tmpkey == NULL)
-                    goto error;
-            }
-            else
-#endif
-            {
-                PyErr_SetString(PyExc_TypeError,
-                                "enumerators must be a list of strings");
-                goto error;
-            }
-        }
-        if (convert_from_object((char*)&lvalue, basetd, value) < 0)
-            goto error;     /* out-of-range or badly typed 'value' */
-        if (PyDict_SetItem(dict1, tmpkey, value) < 0)
-            goto error;
-        if (PyDict_SetItem(dict2, value, tmpkey) < 0)
-            goto error;
-        Py_DECREF(tmpkey);
-        tmpkey = NULL;
-    }
-
-    combined = PyTuple_Pack(2, dict1, dict2);
-    if (combined == NULL)
-        goto error;
-
-    Py_CLEAR(dict2);
-    Py_CLEAR(dict1);
-
-    name_size = strlen(ename) + 1;
-    td = ctypedescr_new(name_size);
-    if (td == NULL)
-        goto error;
-
-    memcpy(td->ct_name, ename, name_size);
-    td->ct_stuff = combined;
-    td->ct_size = basetd->ct_size;
-    td->ct_length = basetd->ct_length;   /* alignment */
-    td->ct_extra = basetd->ct_extra;     /* ffi type  */
-    td->ct_flags = basetd->ct_flags | CT_IS_ENUM;
-    td->ct_name_position = name_size - 1;
-    return (PyObject *)td;
-
- error:
-    Py_XDECREF(tmpkey);
-    Py_XDECREF(combined);
-    Py_XDECREF(dict2);
-    Py_XDECREF(dict1);
-    return NULL;
-}
-
-static PyObject *b_alignof(PyObject *self, PyObject *arg)
-{
-    int align;
-    if (!CTypeDescr_Check(arg)) {
-        PyErr_SetString(PyExc_TypeError, "expected a 'ctype' object");
-        return NULL;
-    }
-    align = get_alignment((CTypeDescrObject *)arg);
-    if (align < 0)
-        return NULL;
-    return PyInt_FromLong(align);
-}
-
-static Py_ssize_t direct_sizeof_cdata(CDataObject *cd)
-{
-    Py_ssize_t size;
-    if (cd->c_type->ct_flags & CT_ARRAY)
-        size = get_array_length(cd) * cd->c_type->ct_itemdescr->ct_size;
-    else {
-        size = -1;
-        if (cd->c_type->ct_flags & (CT_STRUCT | CT_UNION))
-            size = _cdata_var_byte_size(cd);
-        if (size < 0)
-            size = cd->c_type->ct_size;
-    }
-    return size;
-}
-
-static PyObject *b_sizeof(PyObject *self, PyObject *arg)
-{
-    Py_ssize_t size;
-
-    if (CData_Check(arg)) {
-        size = direct_sizeof_cdata((CDataObject *)arg);
-    }
-    else if (CTypeDescr_Check(arg)) {
-        size = ((CTypeDescrObject *)arg)->ct_size;
-        if (size < 0) {
-            PyErr_Format(PyExc_ValueError, "ctype '%s' is of unknown size",
-                         ((CTypeDescrObject *)arg)->ct_name);
-            return NULL;
-        }
-    }
-    else {
-        PyErr_SetString(PyExc_TypeError,
-                        "expected a 'cdata' or 'ctype' object");
-        return NULL;
-    }
-    return PyInt_FromSsize_t(size);
-}
-
-static PyObject *b_typeof(PyObject *self, PyObject *arg)
-{
-    PyObject *res;
-
-    if (!CData_Check(arg)) {
-        PyErr_SetString(PyExc_TypeError, "expected a 'cdata' object");
-        return NULL;
-    }
-    res = (PyObject *)((CDataObject *)arg)->c_type;
-    Py_INCREF(res);
-    return res;
-}
-
-static CTypeDescrObject *direct_typeoffsetof(CTypeDescrObject *ct,
-                                             PyObject *fieldname,
-                                             int following, Py_ssize_t *offset)
-{
-    /* Does not return a new reference! */
-    CTypeDescrObject *res;
-    CFieldObject *cf;
-
-    if (PyTextAny_Check(fieldname)) {
-        if (!following && (ct->ct_flags & CT_POINTER))
-            ct = ct->ct_itemdescr;
-        if (!(ct->ct_flags & (CT_STRUCT|CT_UNION))) {
-            PyErr_SetString(PyExc_TypeError,
-                            "with a field name argument, expected a "
-                            "struct or union ctype");
-            return NULL;
-        }
-        if (force_lazy_struct(ct) <= 0) {
-            if (!PyErr_Occurred())
-                PyErr_SetString(PyExc_TypeError, "struct/union is opaque");
-            return NULL;
-        }
-        cf = (CFieldObject *)PyDict_GetItem(ct->ct_stuff, fieldname);
-        if (cf == NULL) {
-            PyErr_SetObject(PyExc_KeyError, fieldname);
-            return NULL;
-        }
-        if (cf->cf_bitshift >= 0) {
-            PyErr_SetString(PyExc_TypeError, "not supported for bitfields");
-            return NULL;
-        }
-        res = cf->cf_type;
-        *offset = cf->cf_offset;
-    }
-    else {
-        Py_ssize_t index = PyInt_AsSsize_t(fieldname);
-        if (index < 0 && PyErr_Occurred()) {
-            PyErr_SetString(PyExc_TypeError,
-                            "field name or array index expected");
-            return NULL;
-        }
-
-        if (!(ct->ct_flags & (CT_ARRAY|CT_POINTER)) ||
-                ct->ct_itemdescr->ct_size < 0) {
-            PyErr_SetString(PyExc_TypeError, "with an integer argument, "
-                                             "expected an array ctype or a "
-                                             "pointer to non-opaque");
-            return NULL;
-        }
-        res = ct->ct_itemdescr;
-        *offset = MUL_WRAPAROUND(index, ct->ct_itemdescr->ct_size);
-        if ((*offset / ct->ct_itemdescr->ct_size) != index) {
-            PyErr_SetString(PyExc_OverflowError,
-                            "array offset would overflow a Py_ssize_t");
-            return NULL;
-        }
-    }
-    return res;
-}
-
-static PyObject *b_typeoffsetof(PyObject *self, PyObject *args)
-{
-    PyObject *res, *fieldname;
-    CTypeDescrObject *ct;
-    Py_ssize_t offset;
-    int following = 0;
-
-    if (!PyArg_ParseTuple(args, "O!O|i:typeoffsetof",
-                          &CTypeDescr_Type, &ct, &fieldname, &following))
-        return NULL;
-
-    res = (PyObject *)direct_typeoffsetof(ct, fieldname, following, &offset);
-    if (res == NULL)
-        return NULL;
-
-    return Py_BuildValue("(On)", res, offset);
-}
-
-static PyObject *b_rawaddressof(PyObject *self, PyObject *args)
-{
-    CTypeDescrObject *ct;
-    CDataObject *cd;
-    Py_ssize_t offset;
-    int accepted_flags;
-
-    if (!PyArg_ParseTuple(args, "O!O!n:rawaddressof",
-                          &CTypeDescr_Type, &ct,
-                          &CData_Type, &cd,
-                          &offset))
-        return NULL;
-
-    accepted_flags = CT_STRUCT | CT_UNION | CT_ARRAY | CT_POINTER;
-    if ((cd->c_type->ct_flags & accepted_flags) == 0) {
-        PyErr_SetString(PyExc_TypeError,
-                        "expected a cdata struct/union/array/pointer object");
-        return NULL;
-    }
-    if ((ct->ct_flags & CT_POINTER) == 0) {
-        PyErr_SetString(PyExc_TypeError,
-                        "expected a pointer ctype");
-        return NULL;
-    }
-    return new_simple_cdata(cd->c_data + offset, ct);
-}
-
-static PyObject *b_getcname(PyObject *self, PyObject *args)
-{
-    CTypeDescrObject *ct;
-    char *replace_with, *p, *s;
-    Py_ssize_t namelen, replacelen;
-
-    if (!PyArg_ParseTuple(args, "O!s:getcname",
-                          &CTypeDescr_Type, &ct, &replace_with))
-        return NULL;
-
-    namelen = strlen(ct->ct_name);
-    replacelen = strlen(replace_with);
-    s = p = alloca(namelen + replacelen + 1);
-    memcpy(p, ct->ct_name, ct->ct_name_position);
-    p += ct->ct_name_position;
-    memcpy(p, replace_with, replacelen);
-    p += replacelen;
-    memcpy(p, ct->ct_name + ct->ct_name_position,
-           namelen - ct->ct_name_position);
-
-    return PyText_FromStringAndSize(s, namelen + replacelen);
-}
-
-static PyObject *b_string(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    CDataObject *cd;
-    Py_ssize_t maxlen = -1;
-    static char *keywords[] = {"cdata", "maxlen", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|n:string", keywords,
-                                     &CData_Type, &cd, &maxlen))
-        return NULL;
-
-    if (cd->c_type->ct_itemdescr != NULL &&
-        cd->c_type->ct_itemdescr->ct_flags & (CT_PRIMITIVE_CHAR |
-                                              CT_PRIMITIVE_SIGNED |
-                                              CT_PRIMITIVE_UNSIGNED) &&
-        !(cd->c_type->ct_itemdescr->ct_flags & CT_IS_BOOL)) {
-        Py_ssize_t length = maxlen;
-        if (cd->c_data == NULL) {
-            PyObject *s = cdata_repr(cd);
-            if (s != NULL) {
-                PyErr_Format(PyExc_RuntimeError,
-                             "cannot use string() on %s",
-                             PyText_AS_UTF8(s));
-                Py_DECREF(s);
-            }
-            return NULL;
-        }
-        if (length < 0 && cd->c_type->ct_flags & CT_ARRAY) {
-            length = get_array_length(cd);
-        }
-        if (cd->c_type->ct_itemdescr->ct_size == sizeof(char)) {
-            const char *start = cd->c_data;
-            if (length < 0) {
-                /*READ(start, 1)*/
-                length = strlen(start);
-                /*READ(start, length)*/
-            }
-            else {
-                const char *end;
-                /*READ(start, length)*/
-                end = (const char *)memchr(start, 0, length);
-                if (end != NULL)
-                    length = end - start;
-            }
-            return PyBytes_FromStringAndSize(start, length);
-        }
-        else if (cd->c_type->ct_itemdescr->ct_flags & CT_PRIMITIVE_CHAR) {
-            switch (cd->c_type->ct_itemdescr->ct_size) {
-            case 2: {
-                const cffi_char16_t *start = (cffi_char16_t *)cd->c_data;
-                if (length < 0) {
-                    /*READ(start, 2)*/
-                    length = 0;
-                    while (start[length])
-                        length++;
-                    /*READ(start, 2 * length)*/
-                }
-                else {
-                    /*READ(start, 2 * length)*/
-                    maxlen = length;
-                    length = 0;
-                    while (length < maxlen && start[length])
-                        length++;
-                }
-                return _my_PyUnicode_FromChar16(start, length);
-            }
-            case 4: {
-                const cffi_char32_t *start = (cffi_char32_t *)cd->c_data;
-                if (length < 0) {
-                    /*READ(start, 4)*/
-                    length = 0;
-                    while (start[length])
-                        length++;
-                    /*READ(start, 4 * length)*/
-                }
-                else {
-                    /*READ(start, 4 * length)*/
-                    maxlen = length;
-                    length = 0;
-                    while (length < maxlen && start[length])
-                        length++;
-                }
-                return _my_PyUnicode_FromChar32(start, length);
-            }
-            }
-        }
-    }
-    else if (cd->c_type->ct_flags & CT_IS_ENUM) {
-        return convert_cdata_to_enum_string(cd, 0);
-    }
-    else if (cd->c_type->ct_flags & CT_IS_BOOL) {
-        /* fall through to TypeError */
-    }
-    else if (cd->c_type->ct_flags & (CT_PRIMITIVE_CHAR |
-                                     CT_PRIMITIVE_SIGNED |
-                                     CT_PRIMITIVE_UNSIGNED)) {
-        /*READ(cd->c_data, cd->c_type->ct_size)*/
-        if (cd->c_type->ct_size == sizeof(char))
-            return PyBytes_FromStringAndSize(cd->c_data, 1);
-        else if (cd->c_type->ct_flags & CT_PRIMITIVE_CHAR) {
-            switch (cd->c_type->ct_size) {
-            case 2:
-                return _my_PyUnicode_FromChar16((cffi_char16_t *)cd->c_data, 1);
-            case 4:
-                return _my_PyUnicode_FromChar32((cffi_char32_t *)cd->c_data, 1);
-            }
-        }
-    }
-    PyErr_Format(PyExc_TypeError, "string(): unexpected cdata '%s' argument",
-                 cd->c_type->ct_name);
-    return NULL;
-}
-
-static PyObject *b_unpack(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    CDataObject *cd;
-    CTypeDescrObject *ctitem;
-    Py_ssize_t i, length, itemsize;
-    PyObject *result;
-    char *src;
-    int casenum;
-    static char *keywords[] = {"cdata", "length", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!n:unpack", keywords,
-                                     &CData_Type, &cd, &length))
-        return NULL;
-
-    if (!(cd->c_type->ct_flags & (CT_ARRAY|CT_POINTER))) {
-        PyErr_Format(PyExc_TypeError,
-                     "expected a pointer or array, got '%s'",
-                     cd->c_type->ct_name);
-        return NULL;
-    }
-    if (length < 0) {
-        PyErr_SetString(PyExc_ValueError, "'length' cannot be negative");
-        return NULL;
-    }
-    if (cd->c_data == NULL) {
-        PyObject *s = cdata_repr(cd);
-        if (s != NULL) {
-            PyErr_Format(PyExc_RuntimeError,
-                         "cannot use unpack() on %s",
-                         PyText_AS_UTF8(s));
-            Py_DECREF(s);
-        }
-        return NULL;
-    }
-
-    /* byte- and unicode strings */
-    ctitem = cd->c_type->ct_itemdescr;
-    if (ctitem->ct_flags & CT_PRIMITIVE_CHAR) {
-        switch (ctitem->ct_size) {
-        case sizeof(char):
-            return PyBytes_FromStringAndSize(cd->c_data, length);
-        case 2:
-            return _my_PyUnicode_FromChar16((cffi_char16_t *)cd->c_data,length);
-        case 4:
-            return _my_PyUnicode_FromChar32((cffi_char32_t *)cd->c_data,length);
-        }
-    }
-
-    /* else, the result is a list.  This implementation should be
-       equivalent to but much faster than '[p[i] for i in range(length)]'.
-       (Note that on PyPy, 'list(p[0:length])' should be equally fast,
-       but arguably, finding out that there *is* such an unexpected way
-       to write things down is the real problem.)
-    */
-    result = PyList_New(length);
-    if (result == NULL)
-        return NULL;
-
-    src = cd->c_data;
-    itemsize = ctitem->ct_size;
-    if (itemsize < 0) {
-        Py_DECREF(result);
-        PyErr_Format(PyExc_ValueError, "'%s' points to items of unknown size",
-                     cd->c_type->ct_name);
-        return NULL;
-    }
-
-    /* Determine some common fast-paths for the loop below.  The case -1
-       is the fall-back, which always gives the right answer. */
-
-#define ALIGNMENT_CHECK(align)                          \
-        (((align) & ((align) - 1)) == 0 &&              \
-         (((uintptr_t)src) & ((align) - 1)) == 0)
-
-    casenum = -1;
-
-    if ((ctitem->ct_flags & CT_PRIMITIVE_ANY) &&
-            ALIGNMENT_CHECK(ctitem->ct_length)) {
-        /* Source data is fully aligned; we can directly read without
-           memcpy().  The unaligned case is expected to be rare; in
-           this situation it is ok to fall back to the general
-           convert_to_object() in the loop.  For now we also use this
-           fall-back for types that are too large.
-        */
-        if (ctitem->ct_flags & CT_PRIMITIVE_SIGNED) {
-            if (itemsize == sizeof(long))             casenum = 3;
-            else if (itemsize == sizeof(int))         casenum = 2;
-            else if (itemsize == sizeof(short))       casenum = 1;
-            else if (itemsize == sizeof(signed char)) casenum = 0;
-        }
-        else if (ctitem->ct_flags & CT_PRIMITIVE_UNSIGNED) {
-            /* Note: we never pick case 6 if sizeof(int) == sizeof(long),
-               so that case 6 below can assume that the 'unsigned int' result
-               would always fit in a 'signed long'. */
-            if (ctitem->ct_flags & CT_IS_BOOL)           casenum = 11;
-            else if (itemsize == sizeof(unsigned long))  casenum = 7;
-            else if (itemsize == sizeof(unsigned int))   casenum = 6;
-            else if (itemsize == sizeof(unsigned short)) casenum = 5;
-            else if (itemsize == sizeof(unsigned char))  casenum = 4;
-        }
-        else if (ctitem->ct_flags & CT_PRIMITIVE_FLOAT) {
-            if      (itemsize == sizeof(double)) casenum = 9;
-            else if (itemsize == sizeof(float))  casenum = 8;
-        }
-    }
-    else if (ctitem->ct_flags & (CT_POINTER | CT_FUNCTIONPTR)) {
-        casenum = 10;    /* any pointer */
-    }
-#undef ALIGNMENT_CHECK
-
-    for (i = 0; i < length; i++) {
-        PyObject *x;
-        switch (casenum) {
-            /* general case */
-        default: x = convert_to_object(src, ctitem); break;
-
-            /* special cases for performance only */
-        case 0: x = PyInt_FromLong(*(signed char *)src); break;
-        case 1: x = PyInt_FromLong(*(short *)src); break;
-        case 2: x = PyInt_FromLong(*(int *)src); break;
-        case 3: x = PyInt_FromLong(*(long *)src); break;
-        case 4: x = PyInt_FromLong(*(unsigned char *)src); break;
-        case 5: x = PyInt_FromLong(*(unsigned short *)src); break;
-        case 6: x = PyInt_FromLong((long)*(unsigned int *)src); break;
-        case 7: x = PyLong_FromUnsignedLong(*(unsigned long *)src); break;
-        case 8: x = PyFloat_FromDouble(*(float *)src); break;
-        case 9: x = PyFloat_FromDouble(*(double *)src); break;
-        case 10: x = new_simple_cdata(*(char **)src, ctitem); break;
-        case 11:
-            switch (*(unsigned char *)src) {
-            case 0: x = Py_False; Py_INCREF(x); break;
-            case 1: x = Py_True;  Py_INCREF(x); break;
-            default: x = convert_to_object(src, ctitem); /* error */
-            }
-            break;
-        }
-        if (x == NULL) {
-            Py_DECREF(result);
-            return NULL;
-        }
-        PyList_SET_ITEM(result, i, x);
-        src += itemsize;
-    }
-    return result;
-}
-
-static PyObject *
-b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    /* this is the constructor of the type implemented in minibuffer.h */
-    CDataObject *cd;
-    Py_ssize_t size = -1;
-    static char *keywords[] = {"cdata", "size", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|n:buffer", keywords,
-                                     &CData_Type, &cd, &size))
-        return NULL;
-
-    if (size < 0)
-        size = _cdata_var_byte_size(cd);
-
-    if (cd->c_type->ct_flags & CT_POINTER) {
-        if (size < 0)
-            size = cd->c_type->ct_itemdescr->ct_size;
-    }
-    else if (cd->c_type->ct_flags & CT_ARRAY) {
-        if (size < 0)
-            size = get_array_length(cd) * cd->c_type->ct_itemdescr->ct_size;
-    }
-    else {
-        PyErr_Format(PyExc_TypeError,
-                     "expected a pointer or array cdata, got '%s'",
-                     cd->c_type->ct_name);
-        return NULL;
-    }
-    if (size < 0) {
-        PyErr_Format(PyExc_TypeError,
-                     "don't know the size pointed to by '%s'",
-                     cd->c_type->ct_name);
-        return NULL;
-    }
-    /*WRITE(cd->c_data, size)*/
-    return minibuffer_new(cd->c_data, size, (PyObject *)cd);
-}
-
-static PyObject *b_get_errno(PyObject *self, PyObject *noarg)
-{
-    int err;
-    restore_errno_only();
-    err = errno;
-    errno = 0;
-    return PyInt_FromLong(err);
-}
-
-static PyObject *b_set_errno(PyObject *self, PyObject *arg)
-{
-    long ival = PyInt_AsLong(arg);
-    if (ival == -1 && PyErr_Occurred())
-        return NULL;
-    else if (ival < INT_MIN || ival > INT_MAX) {
-        PyErr_SetString(PyExc_OverflowError, "errno value too large");
-        return NULL;
-    }
-    errno = (int)ival;
-    save_errno_only();
-    errno = 0;
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *newp_handle(CTypeDescrObject *ct_voidp, PyObject *x)
-{
-    CDataObject_own_structptr *cd;
-    cd = (CDataObject_own_structptr *)PyObject_GC_New(CDataObject_own_structptr,
-                                                      &CDataOwningGC_Type);
-    if (cd == NULL)
-        return NULL;
-    Py_INCREF(ct_voidp);        /* must be "void *" */
-    cd->head.c_type = ct_voidp;
-    cd->head.c_data = (char *)cd;
-    cd->head.c_weakreflist = NULL;
-    Py_INCREF(x);
-    cd->structobj = x;
-    PyObject_GC_Track(cd);
-    return (PyObject *)cd;
-}
-
-static PyObject *b_newp_handle(PyObject *self, PyObject *args)
-{
-    CTypeDescrObject *ct;
-    PyObject *x;
-    if (!PyArg_ParseTuple(args, "O!O", &CTypeDescr_Type, &ct, &x))
-        return NULL;
-
-    if (!(ct->ct_flags & CT_IS_VOID_PTR)) {
-        PyErr_Format(PyExc_TypeError, "needs 'void *', got '%s'", ct->ct_name);
-        return NULL;
-    }
-
-    return newp_handle(ct, x);
-}
-
-static PyObject *b_from_handle(PyObject *self, PyObject *arg)
-{
-    CTypeDescrObject *ct;
-    CDataObject_own_structptr *orgcd;
-    PyObject *x;
-    if (!CData_Check(arg)) {
-        PyErr_SetString(PyExc_TypeError, "expected a 'cdata' object");
-        return NULL;
-    }
-    ct = ((CDataObject *)arg)->c_type;
-    if (!(ct->ct_flags & CT_IS_VOIDCHAR_PTR)) {
-        PyErr_Format(PyExc_TypeError,
-                     "expected a 'cdata' object with a 'void *' out of "
-                     "new_handle(), got '%s'", ct->ct_name);
-        return NULL;
-    }
-    orgcd = (CDataObject_own_structptr *)((CDataObject *)arg)->c_data;
-    if (!orgcd) {
-        PyErr_SetString(PyExc_RuntimeError,
-                        "cannot use from_handle() on NULL pointer");
-        return NULL;
-    }
-    if (Py_REFCNT(orgcd) <= 0 || Py_TYPE(orgcd) != &CDataOwningGC_Type) {
-        Py_FatalError("ffi.from_handle() detected that the address passed "
-                      "points to garbage. If it is really the result of "
-                      "ffi.new_handle(), then the Python object has already "
-                      "been garbage collected");
-    }
-    x = orgcd->structobj;
-    Py_INCREF(x);
-    return x;
-}
-
-static int _my_PyObject_GetContiguousBuffer(PyObject *x, Py_buffer *view,
-                                            int writable_only)
-{
-#if PY_MAJOR_VERSION < 3
-    /* Some objects only support the buffer interface and CPython doesn't
-       translate it into the memoryview interface, mess.  Hack a very
-       minimal content for 'view'.  Don't care if the other fields are
-       uninitialized: we only call PyBuffer_Release(), which only reads
-       'view->obj'. */
-    PyBufferProcs *pb = x->ob_type->tp_as_buffer;
-    if (pb && !pb->bf_releasebuffer) {
-        /* we used to try all three in some vaguely sensible order,
-           i.e. first the write.  But trying to call the write on a
-           read-only buffer fails with TypeError.  So we use a less-
-           sensible order now.  See test_from_buffer_more_cases.
-
-           If 'writable_only', we only try bf_getwritebuffer.
-        */
-        readbufferproc proc = NULL;
-        if (!writable_only) {
-            proc = (readbufferproc)pb->bf_getreadbuffer;
-            if (!proc)
-                proc = (readbufferproc)pb->bf_getcharbuffer;
-        }
-        if (!proc)
-            proc = (readbufferproc)pb->bf_getwritebuffer;
-
-        if (proc && pb->bf_getsegcount) {
-            if ((*pb->bf_getsegcount)(x, NULL) != 1) {
-                PyErr_SetString(PyExc_TypeError,
-                                "expected a single-segment buffer object");
-                return -1;
-            }
-            view->len = (*proc)(x, 0, &view->buf);
-            if (view->len < 0)
-                return -1;
-            view->obj = x;
-            Py_INCREF(x);
-            return 0;
-        }
-    }
-#endif
-
-    if (PyObject_GetBuffer(x, view, writable_only ? PyBUF_WRITABLE
-                                                  : PyBUF_SIMPLE) < 0)
-        return -1;
-
-    if (!PyBuffer_IsContiguous(view, 'A')) {
-        PyBuffer_Release(view);
-        PyErr_SetString(PyExc_TypeError, "contiguous buffer expected");
-        return -1;
-    }
-    return 0;
-}
-
-static PyObject *direct_from_buffer(CTypeDescrObject *ct, PyObject *x,
-                                    int require_writable)
-{
-    CDataObject *cd;
-    Py_buffer *view;
-    Py_ssize_t arraylength, minimumlength = 0;
-
-    if (!(ct->ct_flags & (CT_ARRAY | CT_POINTER))) {
-        PyErr_Format(PyExc_TypeError,
-                     "expected a pointer or array ctype, got '%s'",
-                     ct->ct_name);
-        return NULL;
-    }
-
-    /* PyPy 5.7 can obtain buffers for string (python 2)
-       or bytes (python 3). from_buffer(u"foo") is disallowed.
-     */
-    if (PyUnicode_Check(x)) {
-        PyErr_SetString(PyExc_TypeError,
-                        "from_buffer() cannot return the address "
-                        "of a unicode object");
-        return NULL;
-    }
-
-    view = PyObject_Malloc(sizeof(Py_buffer));
-    if (view == NULL) {
-        PyErr_NoMemory();
-        return NULL;
-    }
-    if (_my_PyObject_GetContiguousBuffer(x, view, require_writable) < 0)
-        goto error1;
-
-    if (ct->ct_flags & CT_POINTER)
-    {
-        arraylength = view->len;   /* number of bytes, not used so far */
-    }
-    else {
-        /* ct->ct_flags & CT_ARRAY */
-        if (ct->ct_length >= 0) {
-            /* it's an array with a fixed length; make sure that the
-               buffer contains enough bytes. */
-            minimumlength = ct->ct_size;
-            arraylength = ct->ct_length;
-        }
-        else {
-            /* it's an open 'array[]' */
-            if (ct->ct_itemdescr->ct_size == 1) {
-                /* fast path, performance only */
-                arraylength = view->len;
-            }
-            else if (ct->ct_itemdescr->ct_size > 0) {
-                /* give it as many items as fit the buffer.  Ignore a
-                   partial last element. */
-                arraylength = view->len / ct->ct_itemdescr->ct_size;
-            }
-            else {
-                /* it's an array 'empty[]'.  Unsupported obscure case:
-                   the problem is that setting the length of the result
-                   to anything large (like SSIZE_T_MAX) is dangerous,
-                   because if someone tries to loop over it, it will
-                   turn effectively into an infinite loop. */
-                PyErr_Format(PyExc_ZeroDivisionError,
-                    "from_buffer('%s', ..): the actual length of the array "
-                    "cannot be computed", ct->ct_name);
-                goto error2;
-            }
-        }
-    }
-    if (view->len < minimumlength) {
-        PyErr_Format(PyExc_ValueError,
-            "buffer is too small (%zd bytes) for '%s' (%zd bytes)",
-            view->len, ct->ct_name, minimumlength);
-        goto error2;
-    }
-
-    cd = (CDataObject *)PyObject_GC_New(CDataObject_frombuf,
-                                        &CDataFromBuf_Type);
-    if (cd == NULL)
-        goto error2;
-
-    Py_INCREF(ct);
-    cd->c_type = ct;
-    cd->c_data = view->buf;
-    cd->c_weakreflist = NULL;
-    ((CDataObject_frombuf *)cd)->length = arraylength;
-    ((CDataObject_frombuf *)cd)->bufferview = view;
-    PyObject_GC_Track(cd);
-    return (PyObject *)cd;
-
- error2:
-    PyBuffer_Release(view);
- error1:
-    PyObject_Free(view);
-    return NULL;
-}
-
-static PyObject *b_from_buffer(PyObject *self, PyObject *args)
-{
-    CTypeDescrObject *ct;
-    PyObject *x;
-    int require_writable = 0;
-
-    if (!PyArg_ParseTuple(args, "O!O|i", &CTypeDescr_Type, &ct, &x,
-                          &require_writable))
-        return NULL;
-
-    return direct_from_buffer(ct, x, require_writable);
-}
-
-static int _fetch_as_buffer(PyObject *x, Py_buffer *view, int writable_only)
-{
-    if (CData_Check(x)) {
-        CTypeDescrObject *ct = ((CDataObject *)x)->c_type;
-        if (!(ct->ct_flags & (CT_POINTER|CT_ARRAY))) {
-            PyErr_Format(PyExc_TypeError,
-                         "expected a pointer or array ctype, got '%s'",
-                         ct->ct_name);
-            return -1;
-        }
-        view->buf = ((CDataObject *)x)->c_data;
-        view->obj = NULL;
-        return 0;
-    }
-    else {
-        return _my_PyObject_GetContiguousBuffer(x, view, writable_only);
-    }
-}
-
-static PyObject *b_memmove(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    PyObject *dest_obj, *src_obj;
-    Py_buffer dest_view, src_view;
-    Py_ssize_t n;
-    static char *keywords[] = {"dest", "src", "n", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOn", keywords,
-                                     &dest_obj, &src_obj, &n))
-        return NULL;
-    if (n < 0) {
-        PyErr_SetString(PyExc_ValueError, "negative size");
-        return NULL;
-    }
-
-    if (_fetch_as_buffer(src_obj, &src_view, 0) < 0) {
-        return NULL;
-    }
-    if (_fetch_as_buffer(dest_obj, &dest_view, 1) < 0) {
-        PyBuffer_Release(&src_view);
-        return NULL;
-    }
-
-    memmove(dest_view.buf, src_view.buf, n);
-
-    PyBuffer_Release(&dest_view);
-    PyBuffer_Release(&src_view);
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *b__get_types(PyObject *self, PyObject *noarg)
-{
-    return PyTuple_Pack(2, (PyObject *)&CData_Type,
-                           (PyObject *)&CTypeDescr_Type);
-}
-
-/* forward, in commontypes.c */
-static PyObject *b__get_common_types(PyObject *self, PyObject *arg);
-
-static PyObject *b_gcp(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    CDataObject *cd;
-    CDataObject *origobj;
-    PyObject *destructor;
-    Py_ssize_t ignored;   /* for pypy */
-    static char *keywords[] = {"cdata", "destructor", "size", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O|n:gc", keywords,
-                                     &CData_Type, &origobj, &destructor,
-                                     &ignored))
-        return NULL;
-
-    if (destructor == Py_None) {
-	if (!PyObject_TypeCheck(origobj, &CDataGCP_Type)) {
-	    PyErr_SetString(PyExc_TypeError,
-			    "Can remove destructor only on a object "
-			    "previously returned by ffi.gc()");
-	    return NULL;
-	}
-	Py_CLEAR(((CDataObject_gcp *)origobj)->destructor);
-	Py_RETURN_NONE;
-    }
-
-    cd = allocate_gcp_object(origobj, origobj->c_type, destructor);
-    return (PyObject *)cd;
-}
-
-static PyObject *b_release(PyObject *self, PyObject *arg)
-{
-    if (!CData_Check(arg)) {
-        PyErr_SetString(PyExc_TypeError, "expected a 'cdata' object");
-        return NULL;
-    }
-    return cdata_exit(arg, NULL);
-}
-
-/************************************************************/
-
-static char _testfunc0(char a, char b)
-{
-    return a + b;
-}
-static long _testfunc1(int a, long b)
-{
-    return (long)a + b;
-}
-static PY_LONG_LONG _testfunc2(PY_LONG_LONG a, PY_LONG_LONG b)
-{
-    return a + b;
-}
-static double _testfunc3(float a, double b)
-{
-    return a + b;
-}
-static float _testfunc4(float a, double b)
-{
-    return (float)(a + b);
-}
-static void _testfunc5(void)
-{
-    errno = errno + 15;
-}
-static int *_testfunc6(int *x)
-{
-    static int y;
-    y = *x - 1000;
-    return &y;
-}
-struct _testfunc7_s { unsigned char a1; short a2; };
-static short _testfunc7(struct _testfunc7_s inlined)
-{
-    return inlined.a1 + inlined.a2;
-}
-static int _testfunc9(int num, ...)
-{
-    va_list vargs;
-    int i, total = 0;
-    va_start(vargs, num);
-    for (i=0; i<num; i++) {
-        int value = va_arg(vargs, int);
-        if (value == 0)
-            value = -66666666;
-        total += value;
-    }
-    va_end(vargs);
-    return total;
-}
-
-static struct _testfunc7_s _testfunc10(int n)
-{
-    struct _testfunc7_s result;
-    result.a1 = n;
-    result.a2 = n * n;
-    return result;
-}
-
-struct _testfunc11_s { int a1, a2; };
-static struct _testfunc11_s _testfunc11(int n)
-{
-    struct _testfunc11_s result;
-    result.a1 = n;
-    result.a2 = n * n;
-    return result;
-}
-
-struct _testfunc12_s { double a1; };
-static struct _testfunc12_s _testfunc12(int n)
-{
-    struct _testfunc12_s result;
-    result.a1 = n;
-    return result;
-}
-
-struct _testfunc13_s { int a1, a2, a3; };
-static struct _testfunc13_s _testfunc13(int n)
-{
-    struct _testfunc13_s result;
-    result.a1 = n;
-    result.a2 = n * n;
-    result.a3 = n * n * n;
-    return result;
-}
-
-struct _testfunc14_s { float a1; };
-static struct _testfunc14_s _testfunc14(int n)
-{
-    struct _testfunc14_s result;
-    result.a1 = (float)n;
-    return result;
-}
-
-struct _testfunc15_s { float a1; int a2; };
-static struct _testfunc15_s _testfunc15(int n)
-{
-    struct _testfunc15_s result;
-    result.a1 = (float)n;
-    result.a2 = n * n;
-    return result;
-}
-
-struct _testfunc16_s { float a1, a2; };
-static struct _testfunc16_s _testfunc16(int n)
-{
-    struct _testfunc16_s result;
-    result.a1 = (float)n;
-    result.a2 = -(float)n;
-    return result;
-}
-
-struct _testfunc17_s { int a1; float a2; };
-static struct _testfunc17_s _testfunc17(int n)
-{
-    struct _testfunc17_s result;
-    result.a1 = n;
-    result.a2 = (float)n * (float)n;
-    return result;
-}
-
-static int _testfunc18(struct _testfunc17_s *ptr)
-{
-    return ptr->a1 + (int)ptr->a2;
-}
-
-static long double _testfunc19(long double x, int count)
-{
-    int i;
-    for (i=0; i<count; i++) {
-        x = 4*x - x*x;
-    }
-    return x;
-}
-
-static short _testfunc20(struct _testfunc7_s *ptr)
-{
-    return ptr->a1 + ptr->a2;
-}
-
-struct _testfunc21_s { int a, b, c, d, e, f, g, h, i, j; };
-static int _testfunc21(struct _testfunc21_s inlined)
-{
-    return ((inlined.a << 0) +
-            (inlined.b << 1) +
-            (inlined.c << 2) +
-            (inlined.d << 3) +
-            (inlined.e << 4) +
-            (inlined.f << 5) +
-            (inlined.g << 6) +
-            (inlined.h << 7) +
-            (inlined.i << 8) +
-            (inlined.j << 9));
-}
-
-struct _testfunc22_s { int a[10]; };
-static struct _testfunc22_s _testfunc22(struct _testfunc22_s s1,
-                                        struct _testfunc22_s s2)
-{
-    struct _testfunc22_s result;
-    int i;
-    for (i=0; i<10; i++)
-        result.a[i] = s1.a[i] - s2.a[i];
-    return result;
-}
-
-static int _testfunc23(char *p)
-{
-    if (p)
-        return 1000 * p[0];
-    return -42;
-}
-
-#if 0   /* libffi doesn't properly support complexes currently */
-        /* also, MSVC might not support _Complex... */
-        /* if this is enabled one day, remember to also add _Complex
-         * arguments in addition to return values. */
-static float _Complex _testfunc24(float a, float b)
-{
-    return a + I*2.0*b;
-}
-static double _Complex _testfunc25(double a, double b)
-{
-    return a + I*2.0*b;
-}
-#endif
-
-static PyObject *b__testfunc(PyObject *self, PyObject *args)
-{
-    /* for testing only */
-    int i;
-    void *f;
-    if (!PyArg_ParseTuple(args, "i:_testfunc", &i))
-        return NULL;
-    switch (i) {
-    case 0: f = &_testfunc0; break;
-    case 1: f = &_testfunc1; break;
-    case 2: f = &_testfunc2; break;
-    case 3: f = &_testfunc3; break;
-    case 4: f = &_testfunc4; break;
-    case 5: f = &_testfunc5; break;
-    case 6: f = &_testfunc6; break;
-    case 7: f = &_testfunc7; break;
-    case 8: f = stderr; break;
-    case 9: f = &_testfunc9; break;
-    case 10: f = &_testfunc10; break;
-    case 11: f = &_testfunc11; break;
-    case 12: f = &_testfunc12; break;
-    case 13: f = &_testfunc13; break;
-    case 14: f = &_testfunc14; break;
-    case 15: f = &_testfunc15; break;
-    case 16: f = &_testfunc16; break;
-    case 17: f = &_testfunc17; break;
-    case 18: f = &_testfunc18; break;
-    case 19: f = &_testfunc19; break;
-    case 20: f = &_testfunc20; break;
-    case 21: f = &_testfunc21; break;
-    case 22: f = &_testfunc22; break;
-    case 23: f = &_testfunc23; break;
-#if 0
-    case 24: f = &_testfunc24; break;
-    case 25: f = &_testfunc25; break;
-#endif
-    default:
-        PyErr_SetNone(PyExc_ValueError);
-        return NULL;
-    }
-    return PyLong_FromVoidPtr(f);
-}
-
-#if PY_MAJOR_VERSION < 3
-static Py_ssize_t _test_segcountproc(PyObject *o, Py_ssize_t *ignored)
-{
-    return 1;
-}
-static Py_ssize_t _test_getreadbuf(PyObject *o, Py_ssize_t i, void **r)
-{
-    static char buf[] = "RDB";
-    *r = buf;
-    return 3;
-}
-static Py_ssize_t _test_getwritebuf(PyObject *o, Py_ssize_t i, void **r)
-{
-    static char buf[] = "WRB";
-    *r = buf;
-    return 3;
-}
-static Py_ssize_t _test_getcharbuf(PyObject *o, Py_ssize_t i, char **r)
-{
-    static char buf[] = "CHB";
-    *r = buf;
-    return 3;
-}
-#endif
-static int _test_getbuf(PyObject *self, Py_buffer *view, int flags)
-{
-    static char buf[] = "GTB";
-    return PyBuffer_FillInfo(view, self, buf, 3, /*readonly=*/0, flags);
-}
-static int _test_getbuf_ro(PyObject *self, Py_buffer *view, int flags)
-{
-    static char buf[] = "ROB";
-    return PyBuffer_FillInfo(view, self, buf, 3, /*readonly=*/1, flags);
-}
-
-
-static PyObject *b__testbuff(PyObject *self, PyObject *args)
-{
-    /* for testing only */
-    int methods;
-    PyTypeObject *obj;
-    if (!PyArg_ParseTuple(args, "O!i|_testbuff", &PyType_Type, &obj, &methods))
-        return NULL;
-
-    assert(obj->tp_as_buffer != NULL);
-
-#if PY_MAJOR_VERSION < 3
-    obj->tp_as_buffer->bf_getsegcount = &_test_segcountproc;
-    obj->tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER;
-    obj->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
-    if (methods & 1)  obj->tp_as_buffer->bf_getreadbuffer  = &_test_getreadbuf;
-    if (methods & 2)  obj->tp_as_buffer->bf_getwritebuffer = &_test_getwritebuf;
-    if (methods & 4)  obj->tp_as_buffer->bf_getcharbuffer  = &_test_getcharbuf;
-#endif
-    if (methods & 8)  obj->tp_as_buffer->bf_getbuffer      = &_test_getbuf;
-    if (methods & 16) obj->tp_as_buffer->bf_getbuffer      = &_test_getbuf_ro;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *b_init_cffi_1_0_external_module(PyObject *, PyObject *);
-/* forward, see cffi1_module.c */
-
-
-static PyMethodDef FFIBackendMethods[] = {
-    {"load_library", b_load_library, METH_VARARGS},
-    {"new_primitive_type", b_new_primitive_type, METH_VARARGS},
-    {"new_pointer_type", b_new_pointer_type, METH_VARARGS},
-    {"new_array_type", b_new_array_type, METH_VARARGS},
-    {"new_void_type", b_new_void_type, METH_NOARGS},
-    {"new_struct_type", b_new_struct_type, METH_VARARGS},
-    {"new_union_type", b_new_union_type, METH_VARARGS},
-    {"complete_struct_or_union", b_complete_struct_or_union, METH_VARARGS},
-    {"new_function_type", b_new_function_type, METH_VARARGS},
-    {"new_enum_type", b_new_enum_type, METH_VARARGS},
-    {"newp", b_newp, METH_VARARGS},
-    {"cast", b_cast, METH_VARARGS},
-    {"callback", b_callback, METH_VARARGS},
-    {"alignof", b_alignof, METH_O},
-    {"sizeof", b_sizeof, METH_O},
-    {"typeof", b_typeof, METH_O},
-    {"typeoffsetof", b_typeoffsetof, METH_VARARGS},
-    {"rawaddressof", b_rawaddressof, METH_VARARGS},
-    {"getcname", b_getcname, METH_VARARGS},
-    {"string", (PyCFunction)b_string, METH_VARARGS | METH_KEYWORDS},
-    {"unpack", (PyCFunction)b_unpack, METH_VARARGS | METH_KEYWORDS},
-    {"get_errno", b_get_errno, METH_NOARGS},
-    {"set_errno", b_set_errno, METH_O},
-    {"newp_handle", b_newp_handle, METH_VARARGS},
-    {"from_handle", b_from_handle, METH_O},
-    {"from_buffer", b_from_buffer, METH_VARARGS},
-    {"memmove", (PyCFunction)b_memmove, METH_VARARGS | METH_KEYWORDS},
-    {"gcp", (PyCFunction)b_gcp, METH_VARARGS | METH_KEYWORDS},
-    {"release", b_release, METH_O},
-#ifdef MS_WIN32
-    {"getwinerror", (PyCFunction)b_getwinerror, METH_VARARGS | METH_KEYWORDS},
-#endif
-    {"_get_types", b__get_types, METH_NOARGS},
-    {"_get_common_types", b__get_common_types, METH_O},
-    {"_testfunc", b__testfunc, METH_VARARGS},
-    {"_testbuff", b__testbuff, METH_VARARGS},
-    {"_init_cffi_1_0_external_module", b_init_cffi_1_0_external_module, METH_O},
-    {NULL,     NULL}    /* Sentinel */
-};
-
-/************************************************************/
-/* Functions used by '_cffi_N.so', the generated modules    */
-
-#define _cffi_to_c_SIGNED_FN(RETURNTYPE, SIZE)                          \
-static RETURNTYPE _cffi_to_c_i##SIZE(PyObject *obj) {                   \
-    PY_LONG_LONG tmp = _my_PyLong_AsLongLong(obj);                      \
-    if ((tmp > (PY_LONG_LONG)((1ULL<<(SIZE-1)) - 1)) ||                 \
-        (tmp < (PY_LONG_LONG)(0ULL-(1ULL<<(SIZE-1)))))                  \
-        if (!PyErr_Occurred())                                          \
-            return (RETURNTYPE)_convert_overflow(obj, #SIZE "-bit int"); \
-    return (RETURNTYPE)tmp;                                             \
-}
-
-#define _cffi_to_c_UNSIGNED_FN(RETURNTYPE, SIZE)                        \
-static RETURNTYPE _cffi_to_c_u##SIZE(PyObject *obj) {                   \
-    unsigned PY_LONG_LONG tmp = _my_PyLong_AsUnsignedLongLong(obj, 1);  \
-    if (tmp > ~(((unsigned PY_LONG_LONG)-2) << (SIZE-1)))               \
-        if (!PyErr_Occurred())                                          \
-            return (RETURNTYPE)_convert_overflow(obj,                   \
-                                   #SIZE "-bit unsigned int");          \
-    return (RETURNTYPE)tmp;                                             \
-}
-
-_cffi_to_c_SIGNED_FN(int, 8)
-_cffi_to_c_SIGNED_FN(int, 16)
-_cffi_to_c_SIGNED_FN(int, 32)
-_cffi_to_c_SIGNED_FN(PY_LONG_LONG, 64)
-_cffi_to_c_UNSIGNED_FN(int, 8)
-_cffi_to_c_UNSIGNED_FN(int, 16)
-_cffi_to_c_UNSIGNED_FN(unsigned int, 32)
-_cffi_to_c_UNSIGNED_FN(unsigned PY_LONG_LONG, 64)
-
-static PyObject *_cffi_from_c_pointer(char *ptr, CTypeDescrObject *ct)
-{
-    return convert_to_object((char *)&ptr, ct);
-}
-
-static char *_cffi_to_c_pointer(PyObject *obj, CTypeDescrObject *ct)
-{
-    char *result;
-    if (convert_from_object((char *)&result, ct, obj) < 0) {
-        if ((ct->ct_flags & CT_POINTER) &&
-                (ct->ct_itemdescr->ct_flags & CT_IS_FILE) &&
-                PyFile_Check(obj)) {
-            PyErr_Clear();
-            return (char *)PyFile_AsFile(obj);
-        }
-        return NULL;
-    }
-    return result;
-}
-
-static long double _cffi_to_c_long_double(PyObject *obj)
-{
-    if (CData_Check(obj) &&
-            (((CDataObject *)obj)->c_type->ct_flags & CT_IS_LONGDOUBLE)) {
-        char *data = ((CDataObject *)obj)->c_data;
-        /*READ(data, sizeof(long double))*/
-        return read_raw_longdouble_data(data);
-    }
-    else
-        return PyFloat_AsDouble(obj);
-}
-
-static _Bool _cffi_to_c__Bool(PyObject *obj)
-{
-    PY_LONG_LONG tmp = _my_PyLong_AsLongLong(obj);
-    if (tmp == 0)
-        return 0;
-    else if (tmp == 1)
-        return 1;
-    else if (PyErr_Occurred())
-        return (_Bool)-1;
-    else
-        return (_Bool)_convert_overflow(obj, "_Bool");
-}
-
-static PyObject *_cffi_get_struct_layout(Py_ssize_t nums[])
-{
-    PyObject *result;
-    int count = 0;
-    while (nums[count] >= 0)
-        count++;
-
-    result = PyList_New(count);
-    if (result == NULL)
-        return NULL;
-
-    while (--count >= 0) {
-        PyObject *o = PyInt_FromSsize_t(nums[count]);
-        if (o == NULL) {
-            Py_DECREF(result);
-            return NULL;
-        }
-        PyList_SET_ITEM(result, count, o);
-    }
-    return result;
-}
-
-static PyObject *_cffi_from_c_char(char x) {
-    return PyBytes_FromStringAndSize(&x, 1);
-}
-
-/* backward-compatibility hack: instead of _cffi_to_c_char16_t() and
- * _cffi_to_c_char32_t(), we have _cffi_to_c_wchar_t() handling whatever
- * size is wchar_t, and _cffi_to_c_wchar3216_t() handling the opposite.
- */
-#ifdef HAVE_WCHAR_H
-typedef wchar_t cffi_wchar_t;
-#else
-typedef uint16_t cffi_wchar_t;   /* random pick... */
-#endif
-
-static cffi_wchar_t _cffi_to_c_wchar_t(PyObject *init)
-{
-    if (sizeof(cffi_wchar_t) == 2)
-        return (cffi_wchar_t)_convert_to_char16_t(init);
-    else
-        return (cffi_wchar_t)_convert_to_char32_t(init);
-}
-static PyObject *_cffi_from_c_wchar_t(cffi_wchar_t x) {
-    if (sizeof(cffi_wchar_t) == 2) {
-        cffi_char16_t input = x;
-        return _my_PyUnicode_FromChar16(&input, 1);
-    }
-    else {
-        cffi_char32_t input = x;
-        return _my_PyUnicode_FromChar32(&input, 1);
-    }
-}
-static int _cffi_to_c_wchar3216_t(PyObject *init)
-{
-    if (sizeof(cffi_wchar_t) == 4)
-        return (int)_convert_to_char16_t(init);
-    else
-        return (int)_convert_to_char32_t(init);
-}
-static PyObject *_cffi_from_c_wchar3216_t(int x) {
-    if (sizeof(cffi_wchar_t) == 4) {
-        cffi_char16_t input = x;
-        return _my_PyUnicode_FromChar16(&input, 1);
-    }
-    else {
-        cffi_char32_t input = x;
-        return _my_PyUnicode_FromChar32(&input, 1);
-    }
-}
-
-struct _cffi_externpy_s;      /* forward declaration */
-static void cffi_call_python(struct _cffi_externpy_s *, char *args);
-
-static void *cffi_exports[] = {
-    NULL,
-    _cffi_to_c_i8,
-    _cffi_to_c_u8,
-    _cffi_to_c_i16,
-    _cffi_to_c_u16,
-    _cffi_to_c_i32,
-    _cffi_to_c_u32,
-    _cffi_to_c_i64,
-    _cffi_to_c_u64,
-    _convert_to_char,
-    _cffi_from_c_pointer,
-    _cffi_to_c_pointer,
-    _cffi_get_struct_layout,
-    restore_errno,
-    save_errno,
-    _cffi_from_c_char,
-    convert_to_object,
-    convert_from_object,
-    convert_struct_to_owning_object,
-    _cffi_to_c_wchar_t,
-    _cffi_from_c_wchar_t,
-    _cffi_to_c_long_double,
-    _cffi_to_c__Bool,
-    _prepare_pointer_call_argument,
-    convert_array_from_object,
-    cffi_call_python,
-    _cffi_to_c_wchar3216_t,
-    _cffi_from_c_wchar3216_t,
-};
-
-static struct { const char *name; int value; } all_dlopen_flags[] = {
-    { "RTLD_LAZY",     RTLD_LAZY     },
-    { "RTLD_NOW",      RTLD_NOW      },
-    { "RTLD_GLOBAL",   RTLD_GLOBAL   },
-#ifdef RTLD_LOCAL
-    { "RTLD_LOCAL",    RTLD_LOCAL    },
-#else
-    { "RTLD_LOCAL",    0             },
-#endif
-#ifdef RTLD_NODELETE
-    { "RTLD_NODELETE", RTLD_NODELETE },
-#endif
-#ifdef RTLD_NOLOAD
-    { "RTLD_NOLOAD",   RTLD_NOLOAD   },
-#endif
-#ifdef RTLD_DEEPBIND
-    { "RTLD_DEEPBIND", RTLD_DEEPBIND },
-#endif
-    { NULL, 0 }
-};
-
-
-/************************************************************/
-
-#include "cffi1_module.c"
-
-/************************************************************/
-
-#if PY_MAJOR_VERSION >= 3
-static struct PyModuleDef FFIBackendModuleDef = {
-  PyModuleDef_HEAD_INIT,
-  "_cffi_backend",
-  NULL,
-  -1,
-  FFIBackendMethods,
-  NULL, NULL, NULL, NULL
-};
-#define INITERROR return NULL
-
-PyMODINIT_FUNC
-PyInit__cffi_backend(void)
-#else
-#define INITERROR return
-
-PyMODINIT_FUNC
-init_cffi_backend(void)
-#endif
-{
-    PyObject *m, *v;
-    int i;
-    static char init_done = 0;
-    static PyTypeObject *all_types[] = {
-        &dl_type,
-        &CTypeDescr_Type,
-        &CField_Type,
-        &CData_Type,
-        &CDataOwning_Type,
-        &CDataOwningGC_Type,
-        &CDataFromBuf_Type,
-        &CDataGCP_Type,
-        &CDataIter_Type,
-        &MiniBuffer_Type,
-        &FFI_Type,
-        &Lib_Type,
-        &GlobSupport_Type,
-        NULL
-    };
-
-    v = PySys_GetObject("version");
-    if (v == NULL || !PyText_Check(v) ||
-            strncmp(PyText_AS_UTF8(v), PY_VERSION, 3) != 0) {
-        PyErr_Format(PyExc_ImportError,
-                     "this module was compiled for Python %c%c%c",
-                     PY_VERSION[0], PY_VERSION[1], PY_VERSION[2]);
-        INITERROR;
-    }
-
-#if PY_MAJOR_VERSION >= 3
-    m = PyModule_Create(&FFIBackendModuleDef);
-#else
-    m = Py_InitModule("_cffi_backend", FFIBackendMethods);
-#endif
-
-    if (m == NULL)
-        INITERROR;
-
-    if (unique_cache == NULL) {
-        unique_cache = PyDict_New();
-        if (unique_cache == NULL)
-            INITERROR;
-    }
-
-    /* readify all types and add them to the module */
-    for (i = 0; all_types[i] != NULL; i++) {
-        PyTypeObject *tp = all_types[i];
-        PyObject *tpo = (PyObject *)tp;
-        if (strncmp(tp->tp_name, "_cffi_backend.", 14) != 0) {
-            PyErr_Format(PyExc_ImportError,
-                         "'%s' is an ill-formed type name", tp->tp_name);
-            INITERROR;
-        }
-        if (PyType_Ready(tp) < 0)
-            INITERROR;
-
-        Py_INCREF(tpo);
-        if (PyModule_AddObject(m, tp->tp_name + 14, tpo) < 0)
-            INITERROR;
-    }
-
-    if (!init_done) {
-        v = PyText_FromString("_cffi_backend");
-        if (v == NULL || PyDict_SetItemString(CData_Type.tp_dict,
-                                              "__module__", v) < 0)
-            INITERROR;
-        v = PyText_FromString("<cdata>");
-        if (v == NULL || PyDict_SetItemString(CData_Type.tp_dict,
-                                              "__name__", v) < 0)
-            INITERROR;
-        init_done = 1;
-    }
-
-    /* this is for backward compatibility only */
-    v = PyCapsule_New((void *)cffi_exports, "cffi", NULL);
-    if (v == NULL || PyModule_AddObject(m, "_C_API", v) < 0)
-        INITERROR;
-
-    v = PyText_FromString(CFFI_VERSION);
-    if (v == NULL || PyModule_AddObject(m, "__version__", v) < 0)
-        INITERROR;
-
-    if (PyModule_AddIntConstant(m, "FFI_DEFAULT_ABI", FFI_DEFAULT_ABI) < 0 ||
-#if defined(MS_WIN32) && !defined(_WIN64)
-        PyModule_AddIntConstant(m, "FFI_STDCALL", FFI_STDCALL) < 0 ||
-#endif
-        PyModule_AddIntConstant(m, "FFI_CDECL", FFI_DEFAULT_ABI) < 0 ||
-
-#ifdef MS_WIN32
-#  ifdef _WIN64
-        PyModule_AddIntConstant(m, "_WIN", 64) < 0 ||   /* win64 */
-#  else
-        PyModule_AddIntConstant(m, "_WIN", 32) < 0 ||   /* win32 */
-#  endif
-#endif
-        0)
-      INITERROR;
-
-    for (i = 0; all_dlopen_flags[i].name != NULL; i++) {
-        if (PyModule_AddIntConstant(m,
-                                    all_dlopen_flags[i].name,
-                                    all_dlopen_flags[i].value) < 0)
-            INITERROR;
-    }
-
-    init_cffi_tls();
-    if (PyErr_Occurred())
-        INITERROR;
-    init_cffi_tls_zombie();
-    if (PyErr_Occurred())
-        INITERROR;
-
-    if (init_ffi_lib(m) < 0)
-        INITERROR;
-
-#if PY_MAJOR_VERSION >= 3
-    if (init_file_emulator() < 0)
-        INITERROR;
-    return m;
-#endif
-}
diff --git a/c/_cffi_backend.so b/c/_cffi_backend.so
deleted file mode 100755
index 31f7528..0000000
--- a/c/_cffi_backend.so
+++ /dev/null
Binary files differ
diff --git a/c/_dummy_file_cffi_backend.py b/c/_dummy_file_cffi_backend.py
deleted file mode 100644
index e69de29..0000000
--- a/c/_dummy_file_cffi_backend.py
+++ /dev/null
diff --git a/c/_dummy_file_libffi.py b/c/_dummy_file_libffi.py
deleted file mode 100644
index e69de29..0000000
--- a/c/_dummy_file_libffi.py
+++ /dev/null
diff --git a/c/call_python.c b/c/call_python.c
deleted file mode 100644
index d3d2e17..0000000
--- a/c/call_python.c
+++ /dev/null
@@ -1,292 +0,0 @@
-#if PY_VERSION_HEX >= 0x03080000
-# define HAVE_PYINTERPSTATE_GETDICT
-#endif
-
-
-static PyObject *_current_interp_key(void)
-{
-    PyInterpreterState *interp = PyThreadState_GET()->interp;
-#ifdef HAVE_PYINTERPSTATE_GETDICT
-    return PyInterpreterState_GetDict(interp);   /* shared reference */
-#else
-    return interp->modules;
-#endif
-}
-
-static PyObject *_get_interpstate_dict(void)
-{
-    /* Hack around to return a dict that is subinterpreter-local.
-       Does not return a new reference.  Returns NULL in case of
-       error, but without setting any exception.  (If called late
-       during shutdown, we *can't* set an exception!)
-    */
-    static PyObject *attr_name = NULL;
-    PyThreadState *tstate;
-    PyObject *d, *interpdict;
-    int err;
-    PyInterpreterState *interp;
-
-    tstate = PyThreadState_GET();
-    if (tstate == NULL) {
-        /* no thread state! */
-        return NULL;
-    }
-
-    interp = tstate->interp;
-#ifdef HAVE_PYINTERPSTATE_GETDICT
-    interpdict = PyInterpreterState_GetDict(interp);   /* shared reference */
-#else
-    interpdict = interp->builtins;
-#endif
-    if (interpdict == NULL) {
-        /* subinterpreter was cleared already, or is being cleared right now,
-           to a point that is too much for us to continue */
-        return NULL;
-    }
-
-    /* from there on, we know the (sub-)interpreter is still valid */
-
-    if (attr_name == NULL) {
-        attr_name = PyText_InternFromString("__cffi_backend_extern_py");
-        if (attr_name == NULL)
-            goto error;
-    }
-
-    d = PyDict_GetItem(interpdict, attr_name);
-    if (d == NULL) {
-        d = PyDict_New();
-        if (d == NULL)
-            goto error;
-        err = PyDict_SetItem(interpdict, attr_name, d);
-        Py_DECREF(d);   /* if successful, there is one ref left in interpdict */
-        if (err < 0)
-            goto error;
-    }
-    return d;
-
- error:
-    PyErr_Clear();    /* typically a MemoryError */
-    return NULL;
-}
-
-static PyObject *_ffi_def_extern_decorator(PyObject *outer_args, PyObject *fn)
-{
-    const char *s;
-    PyObject *error, *onerror, *infotuple, *old1;
-    int index, err;
-    const struct _cffi_global_s *g;
-    struct _cffi_externpy_s *externpy;
-    CTypeDescrObject *ct;
-    FFIObject *ffi;
-    builder_c_t *types_builder;
-    PyObject *name = NULL;
-    PyObject *interpstate_dict;
-    PyObject *interpstate_key;
-
-    if (!PyArg_ParseTuple(outer_args, "OzOO", &ffi, &s, &error, &onerror))
-        return NULL;
-
-    if (s == NULL) {
-        name = PyObject_GetAttrString(fn, "__name__");
-        if (name == NULL)
-            return NULL;
-        s = PyText_AsUTF8(name);
-        if (s == NULL) {
-            Py_DECREF(name);
-            return NULL;
-        }
-    }
-
-    types_builder = &ffi->types_builder;
-    index = search_in_globals(&types_builder->ctx, s, strlen(s));
-    if (index < 0)
-        goto not_found;
-    g = &types_builder->ctx.globals[index];
-    if (_CFFI_GETOP(g->type_op) != _CFFI_OP_EXTERN_PYTHON)
-        goto not_found;
-    Py_XDECREF(name);
-
-    ct = realize_c_type(types_builder, types_builder->ctx.types,
-                        _CFFI_GETARG(g->type_op));
-    if (ct == NULL)
-        return NULL;
-
-    infotuple = prepare_callback_info_tuple(ct, fn, error, onerror, 0);
-    Py_DECREF(ct);
-    if (infotuple == NULL)
-        return NULL;
-
-    /* don't directly attach infotuple to externpy: in the presence of
-       subinterpreters, each time we switch to a different
-       subinterpreter and call the C function, it will notice the
-       change and look up infotuple from the interpstate_dict.
-    */
-    interpstate_dict = _get_interpstate_dict();
-    if (interpstate_dict == NULL) {
-        Py_DECREF(infotuple);
-        return PyErr_NoMemory();
-    }
-
-    externpy = (struct _cffi_externpy_s *)g->address;
-    interpstate_key = PyLong_FromVoidPtr((void *)externpy);
-    if (interpstate_key == NULL) {
-        Py_DECREF(infotuple);
-        return NULL;
-    }
-
-    err = PyDict_SetItem(interpstate_dict, interpstate_key, infotuple);
-    Py_DECREF(interpstate_key);
-    Py_DECREF(infotuple);    /* interpstate_dict owns the last ref */
-    if (err < 0)
-        return NULL;
-
-    /* force _update_cache_to_call_python() to be called the next time
-       the C function invokes cffi_call_python, to update the cache */
-    old1 = externpy->reserved1;
-    externpy->reserved1 = Py_None;   /* a non-NULL value */
-    Py_INCREF(Py_None);
-    Py_XDECREF(old1);
-
-    /* return the function object unmodified */
-    Py_INCREF(fn);
-    return fn;
-
- not_found:
-    PyErr_Format(FFIError, "ffi.def_extern('%s'): no 'extern \"Python\"' "
-                 "function with this name", s);
-    Py_XDECREF(name);
-    return NULL;
-}
-
-
-static int _update_cache_to_call_python(struct _cffi_externpy_s *externpy)
-{
-    PyObject *interpstate_dict, *interpstate_key, *infotuple, *old1, *new1;
-    PyObject *old2;
-
-    interpstate_dict = _get_interpstate_dict();
-    if (interpstate_dict == NULL)
-        return 4;    /* oops, shutdown issue? */
-
-    interpstate_key = PyLong_FromVoidPtr((void *)externpy);
-    if (interpstate_key == NULL)
-        goto error;
-
-    infotuple = PyDict_GetItem(interpstate_dict, interpstate_key);
-    Py_DECREF(interpstate_key);
-    if (infotuple == NULL)
-        return 3;    /* no ffi.def_extern() from this subinterpreter */
-
-    new1 = _current_interp_key();
-    Py_INCREF(new1);
-    Py_INCREF(infotuple);
-    old1 = (PyObject *)externpy->reserved1;
-    old2 = (PyObject *)externpy->reserved2;
-    externpy->reserved1 = new1;         /* holds a reference        */
-    externpy->reserved2 = infotuple;    /* holds a reference (issue #246) */
-    Py_XDECREF(old1);
-    Py_XDECREF(old2);
-
-    return 0;   /* no error */
-
- error:
-    PyErr_Clear();
-    return 2;   /* out of memory? */
-}
-
-#if (defined(WITH_THREAD) && !defined(_MSC_VER) &&   \
-     !defined(__amd64__) && !defined(__x86_64__) &&   \
-     !defined(__i386__) && !defined(__i386))
-# if defined(HAVE_SYNC_SYNCHRONIZE)
-#   define read_barrier()  __sync_synchronize()
-# elif defined(_AIX)
-#   define read_barrier()  __lwsync()
-# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-#   include <mbarrier.h>
-#   define read_barrier()  __compiler_barrier()
-# elif defined(__hpux)
-#   define read_barrier()  _Asm_mf()
-# else
-#   define read_barrier()  /* missing */
-#   warning "no definition for read_barrier(), missing synchronization for\
- multi-thread initialization in embedded mode"
-# endif
-#else
-# define read_barrier()  (void)0
-#endif
-
-static void cffi_call_python(struct _cffi_externpy_s *externpy, char *args)
-{
-    /* Invoked by the helpers generated from extern "Python" in the cdef.
-
-       'externpy' is a static structure that describes which of the
-       extern "Python" functions is called.  It has got fields 'name' and
-       'type_index' describing the function, and more reserved fields
-       that are initially zero.  These reserved fields are set up by
-       ffi.def_extern(), which invokes _ffi_def_extern_decorator() above.
-
-       'args' is a pointer to an array of 8-byte entries.  Each entry
-       contains an argument.  If an argument is less than 8 bytes, only
-       the part at the beginning of the entry is initialized.  If an
-       argument is 'long double' or a struct/union, then it is passed
-       by reference.
-
-       'args' is also used as the place to write the result to
-       (directly, even if more than 8 bytes).  In all cases, 'args' is
-       at least 8 bytes in size.
-    */
-    int err = 0;
-
-    /* This read barrier is needed for _embedding.h.  It is paired
-       with the write_barrier() there.  Without this barrier, we can
-       in theory see the following situation: the Python
-       initialization code already ran (in another thread), and the
-       '_cffi_call_python' function pointer directed execution here;
-       but any number of other data could still be seen as
-       uninitialized below.  For example, 'externpy' would still
-       contain NULLs even though it was correctly set up, or
-       'interpreter_lock' (the GIL inside CPython) would still be seen
-       as NULL, or 'autoInterpreterState' (used by
-       PyGILState_Ensure()) would be NULL or contain bogus fields.
-    */
-    read_barrier();
-
-    save_errno();
-
-    /* We need the infotuple here.  We could always go through
-       _update_cache_to_call_python(), but to avoid the extra dict
-       lookups, we cache in (reserved1, reserved2) the last seen pair
-       (interp->modules, infotuple).  The first item in this tuple is
-       a random PyObject that identifies the subinterpreter.
-    */
-    if (externpy->reserved1 == NULL) {
-        /* Not initialized!  We didn't call @ffi.def_extern() on this
-           externpy object from any subinterpreter at all. */
-        err = 1;
-    }
-    else {
-        PyGILState_STATE state = gil_ensure();
-        if (externpy->reserved1 != _current_interp_key()) {
-            /* Update the (reserved1, reserved2) cache.  This will fail
-               if we didn't call @ffi.def_extern() in this particular
-               subinterpreter. */
-            err = _update_cache_to_call_python(externpy);
-        }
-        if (!err) {
-            general_invoke_callback(0, args, args, externpy->reserved2);
-        }
-        gil_release(state);
-    }
-    if (err) {
-        static const char *msg[] = {
-            "no code was attached to it yet with @ffi.def_extern()",
-            "got internal exception (out of memory?)",
-            "@ffi.def_extern() was not called in the current subinterpreter",
-            "got internal exception (shutdown issue?)",
-        };
-        fprintf(stderr, "extern \"Python\": function %s() called, "
-                        "but %s.  Returning 0.\n", externpy->name, msg[err-1]);
-        memset(args, 0, externpy->size_of_result);
-    }
-    restore_errno();
-}
diff --git a/c/cdlopen.c b/c/cdlopen.c
deleted file mode 100644
index 0ed319b..0000000
--- a/c/cdlopen.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/* ffi.dlopen() interface with dlopen()/dlsym()/dlclose() */
-
-static void *cdlopen_fetch(PyObject *libname, void *libhandle,
-                           const char *symbol)
-{
-    void *address;
-
-    if (libhandle == NULL) {
-        PyErr_Format(FFIError, "library '%s' has been closed",
-                     PyText_AS_UTF8(libname));
-        return NULL;
-    }
-
-    dlerror();   /* clear error condition */
-    address = dlsym(libhandle, symbol);
-    if (address == NULL) {
-        const char *error = dlerror();
-        PyErr_Format(FFIError, "symbol '%s' not found in library '%s': %s",
-                     symbol, PyText_AS_UTF8(libname), error);
-    }
-    return address;
-}
-
-static void cdlopen_close_ignore_errors(void *libhandle)
-{
-    if (libhandle != NULL)
-        dlclose(libhandle);
-}
-
-static int cdlopen_close(PyObject *libname, void *libhandle)
-{
-    if (libhandle != NULL && dlclose(libhandle) != 0) {
-        const char *error = dlerror();
-        PyErr_Format(FFIError, "closing library '%s': %s",
-                     PyText_AS_UTF8(libname), error);
-        return -1;
-    }
-    return 0;
-}
-
-static PyObject *ffi_dlopen(PyObject *self, PyObject *args)
-{
-    const char *modname;
-    PyObject *temp, *result = NULL;
-    void *handle;
-    int auto_close;
-
-    handle = b_do_dlopen(args, &modname, &temp, &auto_close);
-    if (handle != NULL)
-    {
-        result = (PyObject *)lib_internal_new((FFIObject *)self,
-                                              modname, handle, auto_close);
-    }
-    Py_XDECREF(temp);
-    return result;
-}
-
-static PyObject *ffi_dlclose(PyObject *self, PyObject *args)
-{
-    LibObject *lib;
-    void *libhandle;
-    if (!PyArg_ParseTuple(args, "O!", &Lib_Type, &lib))
-        return NULL;
-
-    libhandle = lib->l_libhandle;
-    if (libhandle != NULL)
-    {
-        lib->l_libhandle = NULL;
-
-        /* Clear the dict to force further accesses to do cdlopen_fetch()
-           again, and fail because the library was closed. */
-        PyDict_Clear(lib->l_dict);
-
-        if (cdlopen_close(lib->l_libname, libhandle) < 0)
-            return NULL;
-    }
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-
-static Py_ssize_t cdl_4bytes(char *src)
-{
-    /* read 4 bytes in little-endian order; return it as a signed integer */
-    signed char *ssrc = (signed char *)src;
-    unsigned char *usrc = (unsigned char *)src;
-    return (ssrc[0] << 24) | (usrc[1] << 16) | (usrc[2] << 8) | usrc[3];
-}
-
-static _cffi_opcode_t cdl_opcode(char *src)
-{
-    return (_cffi_opcode_t)cdl_4bytes(src);
-}
-
-typedef struct {
-    unsigned long long value;
-    int neg;
-} cdl_intconst_t;
-
-static int _cdl_realize_global_int(struct _cffi_getconst_s *gc)
-{
-    /* The 'address' field of 'struct _cffi_global_s' is set to point
-       to this function in case ffiobj_init() sees constant integers.
-       This fishes around after the 'ctx->globals' array, which is
-       initialized to contain another array, this time of
-       'cdl_intconst_t' structures.  We get the nth one and it tells
-       us what to return.
-    */
-    cdl_intconst_t *ic;
-    ic = (cdl_intconst_t *)(gc->ctx->globals + gc->ctx->num_globals);
-    ic += gc->gindex;
-    gc->value = ic->value;
-    return ic->neg;
-}
-
-static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    FFIObject *ffi;
-    static char *keywords[] = {"module_name", "_version", "_types",
-                               "_globals", "_struct_unions", "_enums",
-                               "_typenames", "_includes", NULL};
-    char *ffiname = "?", *types = NULL, *building = NULL;
-    Py_ssize_t version = -1;
-    Py_ssize_t types_len = 0;
-    PyObject *globals = NULL, *struct_unions = NULL, *enums = NULL;
-    PyObject *typenames = NULL, *includes = NULL;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds,
-                                     "|sns#O!O!O!O!O!:FFI", keywords,
-                                     &ffiname, &version, &types, &types_len,
-                                     &PyTuple_Type, &globals,
-                                     &PyTuple_Type, &struct_unions,
-                                     &PyTuple_Type, &enums,
-                                     &PyTuple_Type, &typenames,
-                                     &PyTuple_Type, &includes))
-        return -1;
-
-    ffi = (FFIObject *)self;
-    if (ffi->ctx_is_nonempty) {
-        PyErr_SetString(PyExc_ValueError,
-                        "cannot call FFI.__init__() more than once");
-        return -1;
-    }
-    ffi->ctx_is_nonempty = 1;
-
-    if (version == -1 && types_len == 0)
-        return 0;
-    if (version < CFFI_VERSION_MIN || version > CFFI_VERSION_MAX) {
-        PyErr_Format(PyExc_ImportError,
-                     "cffi out-of-line Python module '%s' has unknown "
-                     "version %p", ffiname, (void *)version);
-        return -1;
-    }
-
-    if (types_len > 0) {
-        /* unpack a string of 4-byte entries into an array of _cffi_opcode_t */
-        _cffi_opcode_t *ntypes;
-        Py_ssize_t i, n = types_len / 4;
-
-        building = PyMem_Malloc(n * sizeof(_cffi_opcode_t));
-        if (building == NULL)
-            goto error;
-        ntypes = (_cffi_opcode_t *)building;
-
-        for (i = 0; i < n; i++) {
-            ntypes[i] = cdl_opcode(types);
-            types += 4;
-        }
-        ffi->types_builder.ctx.types = ntypes;
-        ffi->types_builder.ctx.num_types = n;
-        building = NULL;
-    }
-
-    if (globals != NULL) {
-        /* unpack a tuple alternating strings and ints, each two together
-           describing one global_s entry with no specified address or size.
-           The int is only used with integer constants. */
-        struct _cffi_global_s *nglobs;
-        cdl_intconst_t *nintconsts;
-        Py_ssize_t i, n = PyTuple_GET_SIZE(globals) / 2;
-
-        i = n * (sizeof(struct _cffi_global_s) + sizeof(cdl_intconst_t));
-        building = PyMem_Malloc(i);
-        if (building == NULL)
-            goto error;
-        memset(building, 0, i);
-        nglobs = (struct _cffi_global_s *)building;
-        nintconsts = (cdl_intconst_t *)(nglobs + n);
-
-        for (i = 0; i < n; i++) {
-            char *g = PyBytes_AS_STRING(PyTuple_GET_ITEM(globals, i * 2));
-            nglobs[i].type_op = cdl_opcode(g); g += 4;
-            nglobs[i].name = g;
-            if (_CFFI_GETOP(nglobs[i].type_op) == _CFFI_OP_CONSTANT_INT ||
-                _CFFI_GETOP(nglobs[i].type_op) == _CFFI_OP_ENUM) {
-                PyObject *o = PyTuple_GET_ITEM(globals, i * 2 + 1);
-                nglobs[i].address = &_cdl_realize_global_int;
-#if PY_MAJOR_VERSION < 3
-                if (PyInt_Check(o)) {
-                    nintconsts[i].neg = PyInt_AS_LONG(o) <= 0;
-                    nintconsts[i].value = (long long)PyInt_AS_LONG(o);
-                }
-                else
-#endif
-                {
-                    nintconsts[i].neg = PyObject_RichCompareBool(o, Py_False,
-                                                                 Py_LE);
-                    nintconsts[i].value = PyLong_AsUnsignedLongLongMask(o);
-                    if (PyErr_Occurred())
-                        goto error;
-                }
-            }
-        }
-        ffi->types_builder.ctx.globals = nglobs;
-        ffi->types_builder.ctx.num_globals = n;
-        building = NULL;
-    }
-
-    if (struct_unions != NULL) {
-        /* unpack a tuple of struct/unions, each described as a sub-tuple;
-           the item 0 of each sub-tuple describes the struct/union, and
-           the items 1..N-1 describe the fields, if any */
-        struct _cffi_struct_union_s *nstructs;
-        struct _cffi_field_s *nfields;
-        Py_ssize_t i, n = PyTuple_GET_SIZE(struct_unions);
-        Py_ssize_t nf = 0;   /* total number of fields */
-
-        for (i = 0; i < n; i++) {
-            nf += PyTuple_GET_SIZE(PyTuple_GET_ITEM(struct_unions, i)) - 1;
-        }
-        i = (n * sizeof(struct _cffi_struct_union_s) +
-             nf * sizeof(struct _cffi_field_s));
-        building = PyMem_Malloc(i);
-        if (building == NULL)
-            goto error;
-        memset(building, 0, i);
-        nstructs = (struct _cffi_struct_union_s *)building;
-        nfields = (struct _cffi_field_s *)(nstructs + n);
-        nf = 0;
-
-        for (i = 0; i < n; i++) {
-            /* 'desc' is the tuple of strings (desc_struct, desc_field_1, ..) */
-            PyObject *desc = PyTuple_GET_ITEM(struct_unions, i);
-            Py_ssize_t j, nf1 = PyTuple_GET_SIZE(desc) - 1;
-            char *s = PyBytes_AS_STRING(PyTuple_GET_ITEM(desc, 0));
-            /* 's' is the first string, describing the struct/union */
-            nstructs[i].type_index = cdl_4bytes(s); s += 4;
-            nstructs[i].flags = cdl_4bytes(s); s += 4;
-            nstructs[i].name = s;
-            if (nstructs[i].flags & (_CFFI_F_OPAQUE | _CFFI_F_EXTERNAL)) {
-                nstructs[i].size = (size_t)-1;
-                nstructs[i].alignment = -1;
-                nstructs[i].first_field_index = -1;
-                nstructs[i].num_fields = 0;
-                assert(nf1 == 0);
-            }
-            else {
-                nstructs[i].size = (size_t)-2;
-                nstructs[i].alignment = -2;
-                nstructs[i].first_field_index = nf;
-                nstructs[i].num_fields = nf1;
-            }
-            for (j = 0; j < nf1; j++) {
-                char *f = PyBytes_AS_STRING(PyTuple_GET_ITEM(desc, j + 1));
-                /* 'f' is one of the other strings beyond the first one,
-                   describing one field each */
-                nfields[nf].field_type_op = cdl_opcode(f); f += 4;
-                nfields[nf].field_offset = (size_t)-1;
-                if (_CFFI_GETOP(nfields[nf].field_type_op) != _CFFI_OP_NOOP) {
-                    nfields[nf].field_size = cdl_4bytes(f); f += 4;
-                }
-                else {
-                    nfields[nf].field_size = (size_t)-1;
-                }
-                nfields[nf].name = f;
-                nf++;
-            }
-        }
-        ffi->types_builder.ctx.struct_unions = nstructs;
-        ffi->types_builder.ctx.fields = nfields;
-        ffi->types_builder.ctx.num_struct_unions = n;
-        building = NULL;
-    }
-
-    if (enums != NULL) {
-        /* unpack a tuple of strings, each of which describes one enum_s
-           entry */
-        struct _cffi_enum_s *nenums;
-        Py_ssize_t i, n = PyTuple_GET_SIZE(enums);
-
-        i = n * sizeof(struct _cffi_enum_s);
-        building = PyMem_Malloc(i);
-        if (building == NULL)
-            goto error;
-        memset(building, 0, i);
-        nenums = (struct _cffi_enum_s *)building;
-
-        for (i = 0; i < n; i++) {
-            char *e = PyBytes_AS_STRING(PyTuple_GET_ITEM(enums, i));
-            /* 'e' is a string describing the enum */
-            nenums[i].type_index = cdl_4bytes(e); e += 4;
-            nenums[i].type_prim = cdl_4bytes(e); e += 4;
-            nenums[i].name = e; e += strlen(e) + 1;
-            nenums[i].enumerators = e;
-        }
-        ffi->types_builder.ctx.enums = nenums;
-        ffi->types_builder.ctx.num_enums = n;
-        building = NULL;
-    }
-
-    if (typenames != NULL) {
-        /* unpack a tuple of strings, each of which describes one typename_s
-           entry */
-        struct _cffi_typename_s *ntypenames;
-        Py_ssize_t i, n = PyTuple_GET_SIZE(typenames);
-
-        i = n * sizeof(struct _cffi_typename_s);
-        building = PyMem_Malloc(i);
-        if (building == NULL)
-            goto error;
-        memset(building, 0, i);
-        ntypenames = (struct _cffi_typename_s *)building;
-
-        for (i = 0; i < n; i++) {
-            char *t = PyBytes_AS_STRING(PyTuple_GET_ITEM(typenames, i));
-            /* 't' is a string describing the typename */
-            ntypenames[i].type_index = cdl_4bytes(t); t += 4;
-            ntypenames[i].name = t;
-        }
-        ffi->types_builder.ctx.typenames = ntypenames;
-        ffi->types_builder.ctx.num_typenames = n;
-        building = NULL;
-    }
-
-    if (includes != NULL) {
-        PyObject *included_libs;
-
-        included_libs = PyTuple_New(PyTuple_GET_SIZE(includes));
-        if (included_libs == NULL)
-            return -1;
-
-        Py_INCREF(includes);
-        ffi->types_builder.included_ffis = includes;
-        ffi->types_builder.included_libs = included_libs;
-    }
-
-    /* Above, we took directly some "char *" strings out of the strings,
-       typically from somewhere inside tuples.  Keep them alive by
-       incref'ing the whole input arguments. */
-    Py_INCREF(args);
-    Py_XINCREF(kwds);
-    ffi->types_builder._keepalive1 = args;
-    ffi->types_builder._keepalive2 = kwds;
-    return 0;
-
- error:
-    if (building != NULL)
-        PyMem_Free(building);
-    if (!PyErr_Occurred())
-        PyErr_NoMemory();
-    return -1;
-}
diff --git a/c/cffi1_module.c b/c/cffi1_module.c
deleted file mode 100644
index 06a84fe..0000000
--- a/c/cffi1_module.c
+++ /dev/null
@@ -1,216 +0,0 @@
-
-#include "parse_c_type.c"
-#include "realize_c_type.c"
-
-#define CFFI_VERSION_MIN            0x2601
-#define CFFI_VERSION_CHAR16CHAR32   0x2801
-#define CFFI_VERSION_MAX            0x28FF
-
-typedef struct FFIObject_s FFIObject;
-typedef struct LibObject_s LibObject;
-
-static PyTypeObject FFI_Type;   /* forward */
-static PyTypeObject Lib_Type;   /* forward */
-
-#include "ffi_obj.c"
-#include "cglob.c"
-#include "lib_obj.c"
-#include "cdlopen.c"
-#include "commontypes.c"
-#include "call_python.c"
-
-
-static int init_ffi_lib(PyObject *m)
-{
-    PyObject *x;
-    int i, res;
-    static char init_done = 0;
-
-    if (!init_done) {
-        if (init_global_types_dict(FFI_Type.tp_dict) < 0)
-            return -1;
-
-        FFIError = PyErr_NewException("ffi.error", NULL, NULL);
-        if (FFIError == NULL)
-            return -1;
-        if (PyDict_SetItemString(FFI_Type.tp_dict, "error", FFIError) < 0)
-            return -1;
-        if (PyDict_SetItemString(FFI_Type.tp_dict, "CType",
-                                 (PyObject *)&CTypeDescr_Type) < 0)
-            return -1;
-        if (PyDict_SetItemString(FFI_Type.tp_dict, "CData",
-                                 (PyObject *)&CData_Type) < 0)
-            return -1;
-        if (PyDict_SetItemString(FFI_Type.tp_dict, "buffer",
-                                 (PyObject *)&MiniBuffer_Type) < 0)
-            return -1;
-
-        for (i = 0; all_dlopen_flags[i].name != NULL; i++) {
-            x = PyInt_FromLong(all_dlopen_flags[i].value);
-            if (x == NULL)
-                return -1;
-            res = PyDict_SetItemString(FFI_Type.tp_dict,
-                                       all_dlopen_flags[i].name, x);
-            Py_DECREF(x);
-            if (res < 0)
-                return -1;
-        }
-        init_done = 1;
-    }
-    return 0;
-}
-
-static int make_included_tuples(char *module_name,
-                                const char *const *ctx_includes,
-                                PyObject **included_ffis,
-                                PyObject **included_libs)
-{
-    Py_ssize_t num = 0;
-    const char *const *p_include;
-
-    if (ctx_includes == NULL)
-        return 0;
-
-    for (p_include = ctx_includes; *p_include; p_include++) {
-        num++;
-    }
-    *included_ffis = PyTuple_New(num);
-    *included_libs = PyTuple_New(num);
-    if (*included_ffis == NULL || *included_libs == NULL)
-        goto error;
-
-    num = 0;
-    for (p_include = ctx_includes; *p_include; p_include++) {
-        PyObject *included_ffi, *included_lib;
-        PyObject *m = PyImport_ImportModule(*p_include);
-        if (m == NULL)
-            goto import_error;
-
-        included_ffi = PyObject_GetAttrString(m, "ffi");
-        PyTuple_SET_ITEM(*included_ffis, num, included_ffi);
-
-        included_lib = (included_ffi == NULL) ? NULL :
-                       PyObject_GetAttrString(m, "lib");
-        PyTuple_SET_ITEM(*included_libs, num, included_lib);
-
-        Py_DECREF(m);
-        if (included_lib == NULL)
-            goto import_error;
-
-        if (!FFIObject_Check(included_ffi) ||
-            !LibObject_Check(included_lib))
-            goto import_error;
-        num++;
-    }
-    return 0;
-
- import_error:
-    PyErr_Format(PyExc_ImportError,
-                 "while loading %.200s: failed to import ffi, lib from %.200s",
-                 module_name, *p_include);
- error:
-    Py_XDECREF(*included_ffis); *included_ffis = NULL;
-    Py_XDECREF(*included_libs); *included_libs = NULL;
-    return -1;
-}
-
-static PyObject *_my_Py_InitModule(char *module_name)
-{
-#if PY_MAJOR_VERSION >= 3
-    struct PyModuleDef *module_def, local_module_def = {
-        PyModuleDef_HEAD_INIT,
-        module_name,
-        NULL,
-        -1,
-        NULL, NULL, NULL, NULL, NULL
-    };
-    /* note: the 'module_def' is allocated dynamically and leaks,
-       but anyway the C extension module can never be unloaded */
-    module_def = PyMem_Malloc(sizeof(struct PyModuleDef));
-    if (module_def == NULL)
-        return PyErr_NoMemory();
-    *module_def = local_module_def;
-    return PyModule_Create(module_def);
-#else
-    return Py_InitModule(module_name, NULL);
-#endif
-}
-
-static PyObject *b_init_cffi_1_0_external_module(PyObject *self, PyObject *arg)
-{
-    PyObject *m, *modules_dict;
-    FFIObject *ffi;
-    LibObject *lib;
-    Py_ssize_t version, num_exports;
-    char *module_name, *exports, *module_name_with_lib;
-    void **raw;
-    const struct _cffi_type_context_s *ctx;
-
-    raw = (void **)PyLong_AsVoidPtr(arg);
-    if (raw == NULL)
-        return NULL;
-
-    module_name = (char *)raw[0];
-    version = (Py_ssize_t)raw[1];
-    exports = (char *)raw[2];
-    ctx = (const struct _cffi_type_context_s *)raw[3];
-
-    if (version < CFFI_VERSION_MIN || version > CFFI_VERSION_MAX) {
-        if (!PyErr_Occurred())
-            PyErr_Format(PyExc_ImportError,
-                "cffi extension module '%s' uses an unknown version tag %p. "
-                "This module might need a more recent version of cffi "
-                "than the one currently installed, which is %s",
-                module_name, (void *)version, CFFI_VERSION);
-        return NULL;
-    }
-
-    /* initialize the exports array */
-    num_exports = 25;
-    if (ctx->flags & 1)    /* set to mean that 'extern "Python"' is used */
-        num_exports = 26;
-    if (version >= CFFI_VERSION_CHAR16CHAR32)
-        num_exports = 28;
-    memcpy(exports, (char *)cffi_exports, num_exports * sizeof(void *));
-
-    /* make the module object */
-    m = _my_Py_InitModule(module_name);
-    if (m == NULL)
-        return NULL;
-
-    /* build the FFI and Lib object inside this new module */
-    ffi = ffi_internal_new(&FFI_Type, ctx);
-    Py_XINCREF(ffi);    /* make the ffi object really immortal */
-    if (ffi == NULL || PyModule_AddObject(m, "ffi", (PyObject *)ffi) < 0)
-        return NULL;
-
-    lib = lib_internal_new(ffi, module_name, NULL, 0);
-    if (lib == NULL || PyModule_AddObject(m, "lib", (PyObject *)lib) < 0)
-        return NULL;
-
-    if (make_included_tuples(module_name, ctx->includes,
-                             &ffi->types_builder.included_ffis,
-                             &lib->l_types_builder->included_libs) < 0)
-        return NULL;
-
-    /* add manually 'module_name.lib' in sys.modules:
-       see test_import_from_lib */
-    modules_dict = PySys_GetObject("modules");
-    if (!modules_dict)
-        return NULL;
-    module_name_with_lib = alloca(strlen(module_name) + 5);
-    strcpy(module_name_with_lib, module_name);
-    strcat(module_name_with_lib, ".lib");
-    if (PyDict_SetItemString(modules_dict, module_name_with_lib,
-                             (PyObject *)lib) < 0)
-        return NULL;
-
-#if PY_MAJOR_VERSION >= 3
-    /* add manually 'module_name' in sys.modules: it seems that 
-       Py_InitModule() is not enough to do that */
-    if (PyDict_SetItemString(modules_dict, module_name, m) < 0)
-        return NULL;
-#endif
-
-    return m;
-}
diff --git a/c/cglob.c b/c/cglob.c
deleted file mode 100644
index e97767c..0000000
--- a/c/cglob.c
+++ /dev/null
@@ -1,113 +0,0 @@
-
-typedef void *(*gs_fetch_addr_fn)(void);
-
-typedef struct {
-    PyObject_HEAD
-
-    PyObject         *gs_name;
-    CTypeDescrObject *gs_type;
-    char             *gs_data;
-    gs_fetch_addr_fn  gs_fetch_addr;
-
-} GlobSupportObject;
-
-static void glob_support_dealloc(GlobSupportObject *gs)
-{
-    Py_DECREF(gs->gs_name);
-    Py_DECREF(gs->gs_type);
-    PyObject_Del(gs);
-}
-
-static PyTypeObject GlobSupport_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.__FFIGlobSupport",
-    sizeof(GlobSupportObject),
-    0,
-    (destructor)glob_support_dealloc,           /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_compare */
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    PyObject_GenericGetAttr,                    /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                         /* tp_flags */
-};
-
-#define GlobSupport_Check(ob)  (Py_TYPE(ob) == &GlobSupport_Type)
-
-static PyObject *make_global_var(PyObject *name, CTypeDescrObject *type,
-                                 char *addr, gs_fetch_addr_fn fetch_addr)
-{
-    GlobSupportObject *gs = PyObject_New(GlobSupportObject, &GlobSupport_Type);
-    if (gs == NULL)
-        return NULL;
-
-    Py_INCREF(name);
-    Py_INCREF(type);
-    gs->gs_name = name;
-    gs->gs_type = type;
-    gs->gs_data = addr;
-    gs->gs_fetch_addr = fetch_addr;
-    return (PyObject *)gs;
-}
-
-static void *fetch_global_var_addr(GlobSupportObject *gs)
-{
-    void *data;
-    if (gs->gs_data != NULL) {
-        data = gs->gs_data;
-    }
-    else {
-        Py_BEGIN_ALLOW_THREADS
-        restore_errno();
-        data = gs->gs_fetch_addr();
-        save_errno();
-        Py_END_ALLOW_THREADS
-    }
-    if (data == NULL) {
-        PyErr_Format(FFIError, "global variable '%s' is at address NULL",
-                     PyText_AS_UTF8(gs->gs_name));
-        return NULL;
-    }
-    return data;
-}
-
-static PyObject *read_global_var(GlobSupportObject *gs)
-{
-    void *data = fetch_global_var_addr(gs);
-    if (data == NULL)
-        return NULL;
-    return convert_to_object(data, gs->gs_type);
-}
-
-static int write_global_var(GlobSupportObject *gs, PyObject *obj)
-{
-    void *data = fetch_global_var_addr(gs);
-    if (data == NULL)
-        return -1;
-    return convert_from_object(data, gs->gs_type, obj);
-}
-
-static PyObject *cg_addressof_global_var(GlobSupportObject *gs)
-{
-    void *data;
-    PyObject *x, *ptrtype = new_pointer_type(gs->gs_type);
-    if (ptrtype == NULL)
-        return NULL;
-
-    data = fetch_global_var_addr(gs);
-    if (data != NULL)
-        x = new_simple_cdata(data, (CTypeDescrObject *)ptrtype);
-    else
-        x = NULL;
-    Py_DECREF(ptrtype);
-    return x;
-}
diff --git a/c/commontypes.c b/c/commontypes.c
deleted file mode 100644
index a41c2fd..0000000
--- a/c/commontypes.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/* This file must be kept in alphabetical order.  See test_commontypes.py */
-
-#define EQ(key, value)    key "\0" value   /* string concatenation */
-#ifdef _WIN64
-#  define W32_64(X,Y)  Y
-# else
-#  define W32_64(X,Y)  X
-# endif
-
-
-static const char *common_simple_types[] = {
-
-#ifdef MS_WIN32   /* Windows types */
-    EQ("ATOM", "WORD"),
-    EQ("BOOL", "int"),
-    EQ("BOOLEAN", "BYTE"),
-    EQ("BYTE", "unsigned char"),
-    EQ("CCHAR", "char"),
-    EQ("CHAR", "char"),
-    EQ("COLORREF", "DWORD"),
-    EQ("DWORD", "unsigned long"),
-    EQ("DWORD32", "unsigned int"),
-    EQ("DWORD64", "unsigned long long"),
-    EQ("DWORDLONG", "ULONGLONG"),
-    EQ("DWORD_PTR", "ULONG_PTR"),
-#endif
-
-    EQ("FILE", "struct _IO_FILE"),
-
-#ifdef MS_WIN32   /* more Windows types */
-    EQ("FLOAT", "float"),
-    EQ("HACCEL", "HANDLE"),
-    EQ("HALF_PTR", W32_64("short","int")),
-    EQ("HANDLE", "PVOID"),
-    EQ("HBITMAP", "HANDLE"),
-    EQ("HBRUSH", "HANDLE"),
-    EQ("HCOLORSPACE", "HANDLE"),
-    EQ("HCONV", "HANDLE"),
-    EQ("HCONVLIST", "HANDLE"),
-    EQ("HCURSOR", "HICON"),
-    EQ("HDC", "HANDLE"),
-    EQ("HDDEDATA", "HANDLE"),
-    EQ("HDESK", "HANDLE"),
-    EQ("HDROP", "HANDLE"),
-    EQ("HDWP", "HANDLE"),
-    EQ("HENHMETAFILE", "HANDLE"),
-    EQ("HFILE", "int"),
-    EQ("HFONT", "HANDLE"),
-    EQ("HGDIOBJ", "HANDLE"),
-    EQ("HGLOBAL", "HANDLE"),
-    EQ("HHOOK", "HANDLE"),
-    EQ("HICON", "HANDLE"),
-    EQ("HINSTANCE", "HANDLE"),
-    EQ("HKEY", "HANDLE"),
-    EQ("HKL", "HANDLE"),
-    EQ("HLOCAL", "HANDLE"),
-    EQ("HMENU", "HANDLE"),
-    EQ("HMETAFILE", "HANDLE"),
-    EQ("HMODULE", "HINSTANCE"),
-    EQ("HMONITOR", "HANDLE"),
-    EQ("HPALETTE", "HANDLE"),
-    EQ("HPEN", "HANDLE"),
-    EQ("HRESULT", "LONG"),
-    EQ("HRGN", "HANDLE"),
-    EQ("HRSRC", "HANDLE"),
-    EQ("HSZ", "HANDLE"),
-    EQ("HWND", "HANDLE"),
-    EQ("INT", "int"),
-    EQ("INT16", "short"),
-    EQ("INT32", "int"),
-    EQ("INT64", "long long"),
-    EQ("INT8", "signed char"),
-    EQ("INT_PTR", W32_64("int","long long")),
-    EQ("LANGID", "WORD"),
-    EQ("LCID", "DWORD"),
-    EQ("LCTYPE", "DWORD"),
-    EQ("LGRPID", "DWORD"),
-    EQ("LONG", "long"),
-    EQ("LONG32", "int"),
-    EQ("LONG64", "long long"),
-    EQ("LONGLONG", "long long"),
-    EQ("LONG_PTR", W32_64("long","long long")),
-    EQ("LPARAM", "LONG_PTR"),
-    EQ("LPBOOL", "BOOL *"),
-    EQ("LPBYTE", "BYTE *"),
-    EQ("LPCOLORREF", "DWORD *"),
-    EQ("LPCSTR", "const char *"),
-    EQ("LPCVOID", "const void *"),
-    EQ("LPCWSTR", "const WCHAR *"),
-    EQ("LPDWORD", "DWORD *"),
-    EQ("LPHANDLE", "HANDLE *"),
-    EQ("LPINT", "int *"),
-    EQ("LPLONG", "long *"),
-    EQ("LPSTR", "CHAR *"),
-    EQ("LPVOID", "void *"),
-    EQ("LPWORD", "WORD *"),
-    EQ("LPWSTR", "WCHAR *"),
-    EQ("LRESULT", "LONG_PTR"),
-    EQ("PBOOL", "BOOL *"),
-    EQ("PBOOLEAN", "BOOLEAN *"),
-    EQ("PBYTE", "BYTE *"),
-    EQ("PCHAR", "CHAR *"),
-    EQ("PCSTR", "const CHAR *"),
-    EQ("PCWSTR", "const WCHAR *"),
-    EQ("PDWORD", "DWORD *"),
-    EQ("PDWORD32", "DWORD32 *"),
-    EQ("PDWORD64", "DWORD64 *"),
-    EQ("PDWORDLONG", "DWORDLONG *"),
-    EQ("PDWORD_PTR", "DWORD_PTR *"),
-    EQ("PFLOAT", "FLOAT *"),
-    EQ("PHALF_PTR", "HALF_PTR *"),
-    EQ("PHANDLE", "HANDLE *"),
-    EQ("PHKEY", "HKEY *"),
-    EQ("PINT", "int *"),
-    EQ("PINT16", "INT16 *"),
-    EQ("PINT32", "INT32 *"),
-    EQ("PINT64", "INT64 *"),
-    EQ("PINT8", "INT8 *"),
-    EQ("PINT_PTR", "INT_PTR *"),
-    EQ("PLCID", "PDWORD"),
-    EQ("PLONG", "LONG *"),
-    EQ("PLONG32", "LONG32 *"),
-    EQ("PLONG64", "LONG64 *"),
-    EQ("PLONGLONG", "LONGLONG *"),
-    EQ("PLONG_PTR", "LONG_PTR *"),
-    EQ("PSHORT", "SHORT *"),
-    EQ("PSIZE_T", "SIZE_T *"),
-    EQ("PSSIZE_T", "SSIZE_T *"),
-    EQ("PSTR", "CHAR *"),
-    EQ("PUCHAR", "UCHAR *"),
-    EQ("PUHALF_PTR", "UHALF_PTR *"),
-    EQ("PUINT", "UINT *"),
-    EQ("PUINT16", "UINT16 *"),
-    EQ("PUINT32", "UINT32 *"),
-    EQ("PUINT64", "UINT64 *"),
-    EQ("PUINT8", "UINT8 *"),
-    EQ("PUINT_PTR", "UINT_PTR *"),
-    EQ("PULONG", "ULONG *"),
-    EQ("PULONG32", "ULONG32 *"),
-    EQ("PULONG64", "ULONG64 *"),
-    EQ("PULONGLONG", "ULONGLONG *"),
-    EQ("PULONG_PTR", "ULONG_PTR *"),
-    EQ("PUSHORT", "USHORT *"),
-    EQ("PVOID", "void *"),
-    EQ("PWCHAR", "WCHAR *"),
-    EQ("PWORD", "WORD *"),
-    EQ("PWSTR", "WCHAR *"),
-    EQ("QWORD", "unsigned long long"),
-    EQ("SC_HANDLE", "HANDLE"),
-    EQ("SC_LOCK", "LPVOID"),
-    EQ("SERVICE_STATUS_HANDLE", "HANDLE"),
-    EQ("SHORT", "short"),
-    EQ("SIZE_T", "ULONG_PTR"),
-    EQ("SSIZE_T", "LONG_PTR"),
-    EQ("UCHAR", "unsigned char"),
-    EQ("UHALF_PTR", W32_64("unsigned short","unsigned int")),
-    EQ("UINT", "unsigned int"),
-    EQ("UINT16", "unsigned short"),
-    EQ("UINT32", "unsigned int"),
-    EQ("UINT64", "unsigned long long"),
-    EQ("UINT8", "unsigned char"),
-    EQ("UINT_PTR", W32_64("unsigned int","unsigned long long")),
-    EQ("ULONG", "unsigned long"),
-    EQ("ULONG32", "unsigned int"),
-    EQ("ULONG64", "unsigned long long"),
-    EQ("ULONGLONG", "unsigned long long"),
-    EQ("ULONG_PTR", W32_64("unsigned long","unsigned long long")),
-    EQ("USHORT", "unsigned short"),
-    EQ("USN", "LONGLONG"),
-    EQ("VOID", "void"),
-    EQ("WCHAR", "wchar_t"),
-    EQ("WINSTA", "HANDLE"),
-    EQ("WORD", "unsigned short"),
-    EQ("WPARAM", "UINT_PTR"),
-#endif
-
-    EQ("bool", "_Bool"),
-};
-
-
-#undef EQ
-#undef W32_64
-
-#define num_common_simple_types    \
-    (sizeof(common_simple_types) / sizeof(common_simple_types[0]))
-
-
-static const char *get_common_type(const char *search, size_t search_len)
-{
-    const char *entry;
-    int index = search_sorted(common_simple_types, sizeof(const char *),
-                              num_common_simple_types, search, search_len);
-    if (index < 0)
-        return NULL;
-
-    entry = common_simple_types[index];
-    return entry + strlen(entry) + 1;
-}
-
-static PyObject *b__get_common_types(PyObject *self, PyObject *arg)
-{
-    int err;
-    size_t i;
-    for (i = 0; i < num_common_simple_types; i++) {
-        const char *s = common_simple_types[i];
-        PyObject *o = PyText_FromString(s + strlen(s) + 1);
-        if (o == NULL)
-            return NULL;
-        err = PyDict_SetItemString(arg, s, o);
-        Py_DECREF(o);
-        if (err < 0)
-            return NULL;
-    }
-    Py_INCREF(Py_None);
-    return Py_None;
-}
diff --git a/c/ffi_obj.c b/c/ffi_obj.c
deleted file mode 100644
index f154146..0000000
--- a/c/ffi_obj.c
+++ /dev/null
@@ -1,1221 +0,0 @@
-
-/* An FFI object has methods like ffi.new().  It is also a container
-   for the type declarations (typedefs and structs) that you can use,
-   say in ffi.new().
-
-   CTypeDescrObjects are internally stored in the dict 'types_dict'.
-   The types_dict is lazily filled with CTypeDescrObjects made from
-   reading a _cffi_type_context_s structure.
-
-   In "modern" mode, the FFI instance is made by the C extension
-   module originally created by recompile().  The _cffi_type_context_s
-   structure comes from global data in the C extension module.
-
-   In "compatibility" mode, an FFI instance is created explicitly by
-   the user, and its _cffi_type_context_s is initially empty.  You
-   need to call ffi.cdef() to add more information to it.
-*/
-
-#define FFI_COMPLEXITY_OUTPUT   1200     /* xxx should grow as needed */
-
-#define FFIObject_Check(op) PyObject_TypeCheck(op, &FFI_Type)
-#define LibObject_Check(ob)  ((Py_TYPE(ob) == &Lib_Type))
-
-struct FFIObject_s {
-    PyObject_HEAD
-    PyObject *gc_wrefs, *gc_wrefs_freelist;
-    PyObject *init_once_cache;
-    struct _cffi_parse_info_s info;
-    char ctx_is_static, ctx_is_nonempty;
-    builder_c_t types_builder;
-};
-
-static FFIObject *ffi_internal_new(PyTypeObject *ffitype,
-                                 const struct _cffi_type_context_s *static_ctx)
-{
-    static _cffi_opcode_t internal_output[FFI_COMPLEXITY_OUTPUT];
-
-    FFIObject *ffi;
-    if (static_ctx != NULL) {
-        ffi = (FFIObject *)PyObject_GC_New(FFIObject, ffitype);
-        /* we don't call PyObject_GC_Track() here: from _cffi_init_module()
-           it is not needed, because in this case the ffi object is immortal */
-    }
-    else {
-        ffi = (FFIObject *)ffitype->tp_alloc(ffitype, 0);
-    }
-    if (ffi == NULL)
-        return NULL;
-
-    if (init_builder_c(&ffi->types_builder, static_ctx) < 0) {
-        Py_DECREF(ffi);
-        return NULL;
-    }
-    ffi->gc_wrefs = NULL;
-    ffi->gc_wrefs_freelist = NULL;
-    ffi->init_once_cache = NULL;
-    ffi->info.ctx = &ffi->types_builder.ctx;
-    ffi->info.output = internal_output;
-    ffi->info.output_size = FFI_COMPLEXITY_OUTPUT;
-    ffi->ctx_is_static = (static_ctx != NULL);
-    ffi->ctx_is_nonempty = (static_ctx != NULL);
-    return ffi;
-}
-
-static void ffi_dealloc(FFIObject *ffi)
-{
-    PyObject_GC_UnTrack(ffi);
-    Py_XDECREF(ffi->gc_wrefs);
-    Py_XDECREF(ffi->gc_wrefs_freelist);
-    Py_XDECREF(ffi->init_once_cache);
-
-    free_builder_c(&ffi->types_builder, ffi->ctx_is_static);
-
-    Py_TYPE(ffi)->tp_free((PyObject *)ffi);
-}
-
-static int ffi_traverse(FFIObject *ffi, visitproc visit, void *arg)
-{
-    Py_VISIT(ffi->types_builder.types_dict);
-    Py_VISIT(ffi->types_builder.included_ffis);
-    Py_VISIT(ffi->types_builder.included_libs);
-    Py_VISIT(ffi->gc_wrefs);
-    return 0;
-}
-
-static PyObject *ffiobj_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    /* user-facing initialization code, for explicit FFI() calls */
-    return (PyObject *)ffi_internal_new(type, NULL);
-}
-
-/* forward, declared in cdlopen.c because it's mostly useful for this case */
-static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds);
-
-static PyObject *ffi_fetch_int_constant(FFIObject *ffi, const char *name,
-                                        int recursion)
-{
-    int index;
-
-    index = search_in_globals(&ffi->types_builder.ctx, name, strlen(name));
-    if (index >= 0) {
-        const struct _cffi_global_s *g;
-        g = &ffi->types_builder.ctx.globals[index];
-
-        switch (_CFFI_GETOP(g->type_op)) {
-        case _CFFI_OP_CONSTANT_INT:
-        case _CFFI_OP_ENUM:
-            return realize_global_int(&ffi->types_builder, index);
-
-        default:
-            PyErr_Format(FFIError,
-                         "function, global variable or non-integer constant "
-                         "'%.200s' must be fetched from its original 'lib' "
-                         "object", name);
-            return NULL;
-        }
-    }
-
-    if (ffi->types_builder.included_ffis != NULL) {
-        Py_ssize_t i;
-        PyObject *included_ffis = ffi->types_builder.included_ffis;
-
-        if (recursion > 100) {
-            PyErr_SetString(PyExc_RuntimeError,
-                            "recursion overflow in ffi.include() delegations");
-            return NULL;
-        }
-
-        for (i = 0; i < PyTuple_GET_SIZE(included_ffis); i++) {
-            FFIObject *ffi1;
-            PyObject *x;
-
-            ffi1 = (FFIObject *)PyTuple_GET_ITEM(included_ffis, i);
-            x = ffi_fetch_int_constant(ffi1, name, recursion + 1);
-            if (x != NULL || PyErr_Occurred())
-                return x;
-        }
-    }
-    return NULL;     /* no exception set, means "not found" */
-}
-
-#define ACCEPT_STRING   1
-#define ACCEPT_CTYPE    2
-#define ACCEPT_CDATA    4
-#define ACCEPT_ALL      (ACCEPT_STRING | ACCEPT_CTYPE | ACCEPT_CDATA)
-#define CONSIDER_FN_AS_FNPTR  8
-
-static CTypeDescrObject *_ffi_bad_type(FFIObject *ffi, const char *input_text)
-{
-    size_t length = strlen(input_text);
-    char *extra;
-
-    if (length > 500) {
-        extra = "";
-    }
-    else {
-        char *p;
-        size_t i, num_spaces = ffi->info.error_location;
-        extra = alloca(length + num_spaces + 4);
-        p = extra;
-        *p++ = '\n';
-        for (i = 0; i < length; i++) {
-            if (' ' <= input_text[i] && input_text[i] < 0x7f)
-                *p++ = input_text[i];
-            else if (input_text[i] == '\t' || input_text[i] == '\n')
-                *p++ = ' ';
-            else
-                *p++ = '?';
-        }
-        *p++ = '\n';
-        memset(p, ' ', num_spaces);
-        p += num_spaces;
-        *p++ = '^';
-        *p++ = 0;
-    }
-    PyErr_Format(FFIError, "%s%s", ffi->info.error_message, extra);
-    return NULL;
-}
-
-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) {
-            const 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;
-    }
-}
-
-PyDoc_STRVAR(ffi_sizeof_doc,
-"Return the size in bytes of the argument.\n"
-"It can be a string naming a C type, or a 'cdata' instance.");
-
-static PyObject *ffi_sizeof(FFIObject *self, PyObject *arg)
-{
-    Py_ssize_t size;
-
-    if (CData_Check(arg)) {
-        size = direct_sizeof_cdata((CDataObject *)arg);
-    }
-    else {
-        CTypeDescrObject *ct = _ffi_type(self, arg, ACCEPT_ALL);
-        if (ct == NULL)
-            return NULL;
-        size = ct->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);
-}
-
-PyDoc_STRVAR(ffi_alignof_doc,
-"Return the natural alignment size in bytes of the argument.\n"
-"It can be a string naming a C type, or a 'cdata' instance.");
-
-static PyObject *ffi_alignof(FFIObject *self, PyObject *arg)
-{
-    int align;
-    CTypeDescrObject *ct = _ffi_type(self, arg, ACCEPT_ALL);
-    if (ct == NULL)
-        return NULL;
-
-    align = get_alignment(ct);
-    if (align < 0)
-        return NULL;
-    return PyInt_FromLong(align);
-}
-
-PyDoc_STRVAR(ffi_typeof_doc,
-"Parse the C type given as a string and return the\n"
-"corresponding <ctype> object.\n"
-"It can also be used on 'cdata' instance to get its C type.");
-
-static PyObject *_cpyextfunc_type_index(PyObject *x);  /* forward */
-
-static PyObject *ffi_typeof(FFIObject *self, PyObject *arg)
-{
-    PyObject *x = (PyObject *)_ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CDATA);
-    if (x != NULL) {
-        Py_INCREF(x);
-    }
-    else {
-        x = _cpyextfunc_type_index(arg);
-    }
-    return x;
-}
-
-PyDoc_STRVAR(ffi_new_doc,
-"Allocate an instance according to the specified C type and return a\n"
-"pointer to it.  The specified C type must be either a pointer or an\n"
-"array: ``new('X *')`` allocates an X and returns a pointer to it,\n"
-"whereas ``new('X[n]')`` allocates an array of n X'es and returns an\n"
-"array referencing it (which works mostly like a pointer, like in C).\n"
-"You can also use ``new('X[]', n)`` to allocate an array of a\n"
-"non-constant length n.\n"
-"\n"
-"The memory is initialized following the rules of declaring a global\n"
-"variable in C: by default it is zero-initialized, but an explicit\n"
-"initializer can be given which can be used to fill all or part of the\n"
-"memory.\n"
-"\n"
-"When the returned <cdata> object goes out of scope, the memory is\n"
-"freed.  In other words the returned <cdata> object has ownership of\n"
-"the value of type 'cdecl' that it points to.  This means that the raw\n"
-"data can be used as long as this object is kept alive, but must not be\n"
-"used for a longer time.  Be careful about that when copying the\n"
-"pointer to the memory somewhere else, e.g. into another structure.");
-
-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_new(FFIObject *self, PyObject *args, PyObject *kwds)
-{
-    return _ffi_new(self, args, kwds, &default_allocator);
-}
-
-static PyObject *_ffi_new_with_allocator(PyObject *allocator, PyObject *args,
-                                         PyObject *kwds)
-{
-    cffi_allocator_t alloc1;
-    PyObject *my_alloc, *my_free;
-    my_alloc = PyTuple_GET_ITEM(allocator, 1);
-    my_free  = PyTuple_GET_ITEM(allocator, 2);
-    alloc1.ca_alloc = (my_alloc == Py_None ? NULL : my_alloc);
-    alloc1.ca_free  = (my_free  == Py_None ? NULL : my_free);
-    alloc1.ca_dont_clear = (PyTuple_GET_ITEM(allocator, 3) == Py_False);
-
-    return _ffi_new((FFIObject *)PyTuple_GET_ITEM(allocator, 0),
-                    args, kwds, &alloc1);
-}
-
-PyDoc_STRVAR(ffi_new_allocator_doc,
-"Return a new allocator, i.e. a function that behaves like ffi.new()\n"
-"but uses the provided low-level 'alloc' and 'free' functions.\n"
-"\n"
-"'alloc' is called with the size as argument.  If it returns NULL, a\n"
-"MemoryError is raised.  'free' is called with the result of 'alloc'\n"
-"as argument.  Both can be either Python functions or directly C\n"
-"functions.  If 'free' is None, then no free function is called.\n"
-"If both 'alloc' and 'free' are None, the default is used.\n"
-"\n"
-"If 'should_clear_after_alloc' is set to False, then the memory\n"
-"returned by 'alloc' is assumed to be already cleared (or you are\n"
-"fine with garbage); otherwise CFFI will clear it.");
-
-static PyObject *ffi_new_allocator(FFIObject *self, PyObject *args,
-                                   PyObject *kwds)
-{
-    PyObject *allocator, *result;
-    PyObject *my_alloc = Py_None, *my_free = Py_None;
-    int should_clear_after_alloc = 1;
-    static char *keywords[] = {"alloc", "free", "should_clear_after_alloc",
-                               NULL};
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi:new_allocator", keywords,
-                                     &my_alloc, &my_free,
-                                     &should_clear_after_alloc))
-        return NULL;
-
-    if (my_alloc == Py_None && my_free != Py_None) {
-        PyErr_SetString(PyExc_TypeError, "cannot pass 'free' without 'alloc'");
-        return NULL;
-    }
-
-    allocator = PyTuple_Pack(4,
-                             (PyObject *)self,
-                             my_alloc,
-                             my_free,
-                             PyBool_FromLong(should_clear_after_alloc));
-    if (allocator == NULL)
-        return NULL;
-
-    {
-        static PyMethodDef md = {"allocator",
-                                 (PyCFunction)_ffi_new_with_allocator,
-                                 METH_VARARGS | METH_KEYWORDS};
-        result = PyCFunction_New(&md, allocator);
-    }
-    Py_DECREF(allocator);
-    return result;
-}
-
-PyDoc_STRVAR(ffi_cast_doc,
-"Similar to a C cast: returns an instance of the named C\n"
-"type initialized with the given 'source'.  The source is\n"
-"casted between integers or pointers of any type.");
-
-static PyObject *ffi_cast(FFIObject *self, PyObject *args)
-{
-    CTypeDescrObject *ct;
-    PyObject *ob, *arg;
-    if (!PyArg_ParseTuple(args, "OO:cast", &arg, &ob))
-        return NULL;
-
-    ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE);
-    if (ct == NULL)
-        return NULL;
-
-    return do_cast(ct, ob);
-}
-
-PyDoc_STRVAR(ffi_string_doc,
-"Return a Python string (or unicode string) from the 'cdata'.  If\n"
-"'cdata' is a pointer or array of characters or bytes, returns the\n"
-"null-terminated string.  The returned string extends until the first\n"
-"null character, or at most 'maxlen' characters.  If 'cdata' is an\n"
-"array then 'maxlen' defaults to its length.\n"
-"\n"
-"If 'cdata' is a pointer or array of wchar_t, returns a unicode string\n"
-"following the same rules.\n"
-"\n"
-"If 'cdata' is a single character or byte or a wchar_t, returns it as a\n"
-"string or unicode string.\n"
-"\n"
-"If 'cdata' is an enum, returns the value of the enumerator as a\n"
-"string, or 'NUMBER' if the value is out of range.");
-
-#define ffi_string  b_string     /* ffi_string() => b_string()
-                                    from _cffi_backend.c */
-
-PyDoc_STRVAR(ffi_unpack_doc,
-"Unpack an array of C data of the given length,\n"
-"returning a Python string/unicode/list.\n"
-"\n"
-"If 'cdata' is a pointer to 'char', returns a byte string.\n"
-"It does not stop at the first null.  This is equivalent to:\n"
-"ffi.buffer(cdata, length)[:]\n"
-"\n"
-"If 'cdata' is a pointer to 'wchar_t', returns a unicode string.\n"
-"'length' is measured in wchar_t's; it is not the size in bytes.\n"
-"\n"
-"If 'cdata' is a pointer to anything else, returns a list of\n"
-"'length' items.  This is a faster equivalent to:\n"
-"[cdata[i] for i in range(length)]");
-
-#define ffi_unpack  b_unpack     /* ffi_unpack() => b_unpack()
-                                    from _cffi_backend.c */
-
-
-PyDoc_STRVAR(ffi_offsetof_doc,
-"Return the offset of the named field inside the given structure or\n"
-"array, which must be given as a C type name.  You can give several\n"
-"field names in case of nested structures.  You can also give numeric\n"
-"values which correspond to array items, in case of an array type.");
-
-static PyObject *ffi_offsetof(FFIObject *self, PyObject *args)
-{
-    PyObject *arg;
-    CTypeDescrObject *ct;
-    Py_ssize_t i, offset;
-
-    if (PyTuple_Size(args) < 2) {
-        PyErr_SetString(PyExc_TypeError,
-                        "offsetof() expects at least 2 arguments");
-        return NULL;
-    }
-
-    arg = PyTuple_GET_ITEM(args, 0);
-    ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE);
-    if (ct == NULL)
-        return NULL;
-
-    offset = 0;
-    for (i = 1; i < PyTuple_GET_SIZE(args); i++) {
-        Py_ssize_t ofs1;
-        ct = direct_typeoffsetof(ct, PyTuple_GET_ITEM(args, i), i > 1, &ofs1);
-        if (ct == NULL)
-            return NULL;
-        offset += ofs1;
-    }
-    return PyInt_FromSsize_t(offset);
-}
-
-PyDoc_STRVAR(ffi_addressof_doc,
-"Limited equivalent to the '&' operator in C:\n"
-"\n"
-"1. ffi.addressof(<cdata 'struct-or-union'>) returns a cdata that is a\n"
-"pointer to this struct or union.\n"
-"\n"
-"2. ffi.addressof(<cdata>, field-or-index...) returns the address of a\n"
-"field or array item inside the given structure or array, recursively\n"
-"in case of nested structures or arrays.\n"
-"\n"
-"3. ffi.addressof(<library>, \"name\") returns the address of the named\n"
-"function or global variable.");
-
-static PyObject *address_of_global_var(PyObject *args);  /* forward */
-
-static PyObject *ffi_addressof(FFIObject *self, PyObject *args)
-{
-    PyObject *arg, *z, *result;
-    CTypeDescrObject *ct;
-    Py_ssize_t i, offset = 0;
-    int accepted_flags;
-
-    if (PyTuple_Size(args) < 1) {
-        PyErr_SetString(PyExc_TypeError,
-                        "addressof() expects at least 1 argument");
-        return NULL;
-    }
-
-    arg = PyTuple_GET_ITEM(args, 0);
-    if (LibObject_Check(arg)) {
-        /* case 3 in the docstring */
-        return address_of_global_var(args);
-    }
-
-    ct = _ffi_type(self, arg, ACCEPT_CDATA);
-    if (ct == NULL)
-        return NULL;
-
-    if (PyTuple_GET_SIZE(args) == 1) {
-        /* case 1 in the docstring */
-        accepted_flags = CT_STRUCT | CT_UNION | CT_ARRAY;
-        if ((ct->ct_flags & accepted_flags) == 0) {
-            PyErr_SetString(PyExc_TypeError,
-                            "expected a cdata struct/union/array object");
-            return NULL;
-        }
-    }
-    else {
-        /* case 2 in the docstring */
-        accepted_flags = CT_STRUCT | CT_UNION | CT_ARRAY | CT_POINTER;
-        if ((ct->ct_flags & accepted_flags) == 0) {
-            PyErr_SetString(PyExc_TypeError,
-                        "expected a cdata struct/union/array/pointer object");
-            return NULL;
-        }
-        for (i = 1; i < PyTuple_GET_SIZE(args); i++) {
-            Py_ssize_t ofs1;
-            ct = direct_typeoffsetof(ct, PyTuple_GET_ITEM(args, i),
-                                     i > 1, &ofs1);
-            if (ct == NULL)
-                return NULL;
-            offset += ofs1;
-        }
-    }
-
-    z = new_pointer_type(ct);
-    if (z == NULL)
-        return NULL;
-
-    result = new_simple_cdata(((CDataObject *)arg)->c_data + offset,
-                              (CTypeDescrObject *)z);
-    Py_DECREF(z);
-    return result;
-}
-
-static PyObject *_combine_type_name_l(CTypeDescrObject *ct,
-                                      size_t extra_text_len)
-{
-    size_t base_name_len;
-    PyObject *result;
-    char *p;
-
-    base_name_len = strlen(ct->ct_name);
-    result = PyBytes_FromStringAndSize(NULL, base_name_len + extra_text_len);
-    if (result == NULL)
-        return NULL;
-
-    p = PyBytes_AS_STRING(result);
-    memcpy(p, ct->ct_name, ct->ct_name_position);
-    p += ct->ct_name_position;
-    p += extra_text_len;
-    memcpy(p, ct->ct_name + ct->ct_name_position,
-           base_name_len - ct->ct_name_position);
-    return result;
-}
-
-PyDoc_STRVAR(ffi_getctype_doc,
-"Return a string giving the C type 'cdecl', which may be itself a\n"
-"string or a <ctype> object.  If 'replace_with' is given, it gives\n"
-"extra text to append (or insert for more complicated C types), like a\n"
-"variable name, or '*' to get actually the C type 'pointer-to-cdecl'.");
-
-static PyObject *ffi_getctype(FFIObject *self, PyObject *args, PyObject *kwds)
-{
-    PyObject *c_decl, *res;
-    char *p, *replace_with = "";
-    int add_paren, add_space;
-    CTypeDescrObject *ct;
-    size_t replace_with_len;
-    static char *keywords[] = {"cdecl", "replace_with", NULL};
-#if PY_MAJOR_VERSION >= 3
-    PyObject *u;
-#endif
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s:getctype", keywords,
-                                     &c_decl, &replace_with))
-        return NULL;
-
-    ct = _ffi_type(self, c_decl, ACCEPT_STRING|ACCEPT_CTYPE);
-    if (ct == NULL)
-        return NULL;
-
-    while (replace_with[0] != 0 && isspace(replace_with[0]))
-        replace_with++;
-    replace_with_len = strlen(replace_with);
-    while (replace_with_len > 0 && isspace(replace_with[replace_with_len - 1]))
-        replace_with_len--;
-
-    add_paren = (replace_with[0] == '*' &&
-                 ((ct->ct_flags & CT_ARRAY) != 0));
-    add_space = (!add_paren && replace_with_len > 0 &&
-                 replace_with[0] != '[' && replace_with[0] != '(');
-
-    res = _combine_type_name_l(ct, replace_with_len + add_space + 2*add_paren);
-    if (res == NULL)
-        return NULL;
-
-    p = PyBytes_AS_STRING(res) + ct->ct_name_position;
-    if (add_paren)
-        *p++ = '(';
-    if (add_space)
-        *p++ = ' ';
-    memcpy(p, replace_with, replace_with_len);
-    if (add_paren)
-        p[replace_with_len] = ')';
-
-#if PY_MAJOR_VERSION >= 3
-    /* bytes -> unicode string */
-    u = PyUnicode_DecodeLatin1(PyBytes_AS_STRING(res),
-                               PyBytes_GET_SIZE(res),
-                               NULL);
-    Py_DECREF(res);
-    res = u;
-#endif
-
-    return res;
-}
-
-PyDoc_STRVAR(ffi_new_handle_doc,
-"Return a non-NULL cdata of type 'void *' that contains an opaque\n"
-"reference to the argument, which can be any Python object.  To cast it\n"
-"back to the original object, use from_handle().  You must keep alive\n"
-"the cdata object returned by new_handle()!");
-
-static PyObject *ffi_new_handle(FFIObject *self, PyObject *arg)
-{
-    /* g_ct_voidp is equal to <ctype 'void *'> */
-    return newp_handle(g_ct_voidp, arg);
-}
-
-PyDoc_STRVAR(ffi_from_handle_doc,
-"Cast a 'void *' back to a Python object.  Must be used *only* on the\n"
-"pointers returned by new_handle(), and *only* as long as the exact\n"
-"cdata object returned by new_handle() is still alive (somewhere else\n"
-"in the program).  Failure to follow these rules will crash.");
-
-#define ffi_from_handle  b_from_handle   /* ffi_from_handle => b_from_handle
-                                            from _cffi_backend.c */
-
-PyDoc_STRVAR(ffi_from_buffer_doc,
-"Return a <cdata 'char[]'> that points to the data of the given Python\n"
-"object, which must support the buffer interface.  Note that this is\n"
-"not meant to be used on the built-in types str or unicode\n"
-"(you can build 'char[]' arrays explicitly) but only on objects\n"
-"containing large quantities of raw data in some other format, like\n"
-"'array.array' or numpy arrays.");
-
-static PyObject *ffi_from_buffer(FFIObject *self, PyObject *args,
-                                 PyObject *kwds)
-{
-    PyObject *cdecl1, *python_buf = NULL;
-    CTypeDescrObject *ct;
-    int require_writable = 0;
-    static char *keywords[] = {"cdecl", "python_buffer",
-                               "require_writable", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:from_buffer", keywords,
-                                     &cdecl1, &python_buf, &require_writable))
-        return NULL;
-
-    if (python_buf == NULL) {
-        python_buf = cdecl1;
-        ct = g_ct_chararray;
-    }
-    else {
-        ct = _ffi_type(self, cdecl1, ACCEPT_STRING|ACCEPT_CTYPE);
-        if (ct == NULL)
-            return NULL;
-    }
-    return direct_from_buffer(ct, python_buf, require_writable);
-}
-
-PyDoc_STRVAR(ffi_gc_doc,
-"Return a new cdata object that points to the same data.\n"
-"Later, when this new cdata object is garbage-collected,\n"
-"'destructor(old_cdata_object)' will be called.\n"
-"\n"
-"The optional 'size' gives an estimate of the size, used to\n"
-"trigger the garbage collection more eagerly.  So far only used\n"
-"on PyPy.  It tells the GC that the returned object keeps alive\n"
-"roughly 'size' bytes of external memory.");
-
-#define ffi_gc  b_gcp     /* ffi_gc() => b_gcp()
-                             from _cffi_backend.c */
-
-PyDoc_STRVAR(ffi_def_extern_doc,
-"A decorator.  Attaches the decorated Python function to the C code\n"
-"generated for the 'extern \"Python\"' function of the same name.\n"
-"Calling the C function will then invoke the Python function.\n"
-"\n"
-"Optional arguments: 'name' is the name of the C function, if\n"
-"different from the Python function; and 'error' and 'onerror'\n"
-"handle what occurs if the Python function raises an exception\n"
-"(see the docs for details).");
-
-/* forward; see call_python.c */
-static PyObject *_ffi_def_extern_decorator(PyObject *, PyObject *);
-
-static PyObject *ffi_def_extern(FFIObject *self, PyObject *args,
-                                PyObject *kwds)
-{
-    static PyMethodDef md = {"def_extern_decorator",
-                             (PyCFunction)_ffi_def_extern_decorator, METH_O};
-    PyObject *name = Py_None, *error = Py_None;
-    PyObject *res, *onerror = Py_None;
-    static char *keywords[] = {"name", "error", "onerror", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", keywords,
-                                     &name, &error, &onerror))
-        return NULL;
-
-    args = Py_BuildValue("(OOOO)", (PyObject *)self, name, error, onerror);
-    if (args == NULL)
-        return NULL;
-
-    res = PyCFunction_New(&md, args);
-    Py_DECREF(args);
-    return res;
-}
-
-PyDoc_STRVAR(ffi_callback_doc,
-"Return a callback object or a decorator making such a callback object.\n"
-"'cdecl' must name a C function pointer type.  The callback invokes the\n"
-"specified 'python_callable' (which may be provided either directly or\n"
-"via a decorator).  Important: the callback object must be manually\n"
-"kept alive for as long as the callback may be invoked from the C code.");
-
-static PyObject *_ffi_callback_decorator(PyObject *outer_args, PyObject *fn)
-{
-    PyObject *res, *old;
-
-    old = PyTuple_GET_ITEM(outer_args, 1);
-    PyTuple_SET_ITEM(outer_args, 1, fn);
-    res = b_callback(NULL, outer_args);
-    PyTuple_SET_ITEM(outer_args, 1, old);
-    return res;
-}
-
-static PyObject *ffi_callback(FFIObject *self, PyObject *args, PyObject *kwds)
-{
-    PyObject *c_decl, *python_callable = Py_None, *error = Py_None;
-    PyObject *res, *onerror = Py_None;
-    static char *keywords[] = {"cdecl", "python_callable", "error",
-                               "onerror", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", keywords,
-                                     &c_decl, &python_callable, &error,
-                                     &onerror))
-        return NULL;
-
-    c_decl = (PyObject *)_ffi_type(self, c_decl, ACCEPT_STRING | ACCEPT_CTYPE |
-                                                 CONSIDER_FN_AS_FNPTR);
-    if (c_decl == NULL)
-        return NULL;
-
-    args = Py_BuildValue("(OOOO)", c_decl, python_callable, error, onerror);
-    if (args == NULL)
-        return NULL;
-
-    if (python_callable != Py_None) {
-        res = b_callback(NULL, args);
-    }
-    else {
-        static PyMethodDef md = {"callback_decorator",
-                                 (PyCFunction)_ffi_callback_decorator, METH_O};
-        res = PyCFunction_New(&md, args);
-    }
-    Py_DECREF(args);
-    return res;
-}
-
-#ifdef MS_WIN32
-PyDoc_STRVAR(ffi_getwinerror_doc,
-"Return either the GetLastError() or the error number given by the\n"
-"optional 'code' argument, as a tuple '(code, message)'.");
-
-#define ffi_getwinerror  b_getwinerror  /* ffi_getwinerror() => b_getwinerror()
-                                           from misc_win32.h */
-#endif
-
-PyDoc_STRVAR(ffi_errno_doc, "the value of 'errno' from/to the C calls");
-
-static PyObject *ffi_get_errno(PyObject *self, void *closure)
-{
-    /* xxx maybe think about how to make the saved errno local
-       to an ffi instance */
-    return b_get_errno(NULL, NULL);
-}
-
-static int ffi_set_errno(PyObject *self, PyObject *newval, void *closure)
-{
-    PyObject *x = b_set_errno(NULL, newval);
-    if (x == NULL)
-        return -1;
-    Py_DECREF(x);
-    return 0;
-}
-
-PyDoc_STRVAR(ffi_dlopen_doc,
-"Load and return a dynamic library identified by 'name'.  The standard\n"
-"C library can be loaded by passing None.\n"
-"\n"
-"Note that functions and types declared with 'ffi.cdef()' are not\n"
-"linked to a particular library, just like C headers.  In the library\n"
-"we only look for the actual (untyped) symbols at the time of their\n"
-"first access.");
-
-PyDoc_STRVAR(ffi_dlclose_doc,
-"Close a library obtained with ffi.dlopen().  After this call, access to\n"
-"functions or variables from the library will fail (possibly with a\n"
-"segmentation fault).");
-
-static PyObject *ffi_dlopen(PyObject *self, PyObject *args);  /* forward */
-static PyObject *ffi_dlclose(PyObject *self, PyObject *args);  /* forward */
-
-PyDoc_STRVAR(ffi_int_const_doc,
-"Get the value of an integer constant.\n"
-"\n"
-"'ffi.integer_const(\"xxx\")' is equivalent to 'lib.xxx' if xxx names an\n"
-"integer constant.  The point of this function is limited to use cases\n"
-"where you have an 'ffi' object but not any associated 'lib' object.");
-
-static PyObject *ffi_int_const(FFIObject *self, PyObject *args, PyObject *kwds)
-{
-    char *name;
-    PyObject *x;
-    static char *keywords[] = {"name", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", keywords, &name))
-        return NULL;
-
-    x = ffi_fetch_int_constant(self, name, 0);
-
-    if (x == NULL && !PyErr_Occurred()) {
-        PyErr_Format(PyExc_AttributeError,
-                     "integer constant '%.200s' not found", name);
-    }
-    return x;
-}
-
-PyDoc_STRVAR(ffi_list_types_doc,
-"Returns the user type names known to this FFI instance.\n"
-"This returns a tuple containing three lists of names:\n"
-"(typedef_names, names_of_structs, names_of_unions)");
-
-static PyObject *ffi_list_types(FFIObject *self, PyObject *noargs)
-{
-    Py_ssize_t i, n1 = self->types_builder.ctx.num_typenames;
-    Py_ssize_t n23 = self->types_builder.ctx.num_struct_unions;
-    PyObject *o, *lst[3] = {NULL, NULL, NULL}, *result = NULL;
-
-    lst[0] = PyList_New(n1);
-    if (lst[0] == NULL)
-        goto error;
-    lst[1] = PyList_New(0);
-    if (lst[1] == NULL)
-        goto error;
-    lst[2] = PyList_New(0);
-    if (lst[2] == NULL)
-        goto error;
-
-    for (i = 0; i < n1; i++) {
-        o = PyText_FromString(self->types_builder.ctx.typenames[i].name);
-        if (o == NULL)
-            goto error;
-        PyList_SET_ITEM(lst[0], i, o);
-    }
-
-    for (i = 0; i < n23; i++) {
-        const struct _cffi_struct_union_s *s;
-        int err, index;
-
-        s = &self->types_builder.ctx.struct_unions[i];
-        if (s->name[0] == '$')
-            continue;
-
-        o = PyText_FromString(s->name);
-        if (o == NULL)
-            goto error;
-        index = (s->flags & _CFFI_F_UNION) ? 2 : 1;
-        err = PyList_Append(lst[index], o);
-        Py_DECREF(o);
-        if (err < 0)
-            goto error;
-    }
-    result = PyTuple_Pack(3, lst[0], lst[1], lst[2]);
-    /* fall-through */
- error:
-    Py_XDECREF(lst[2]);
-    Py_XDECREF(lst[1]);
-    Py_XDECREF(lst[0]);
-    return result;
-}
-
-PyDoc_STRVAR(ffi_memmove_doc,
-"ffi.memmove(dest, src, n) copies n bytes of memory from src to dest.\n"
-"\n"
-"Like the C function memmove(), the memory areas may overlap;\n"
-"apart from that it behaves like the C function memcpy().\n"
-"\n"
-"'src' can be any cdata ptr or array, or any Python buffer object.\n"
-"'dest' can be any cdata ptr or array, or a writable Python buffer\n"
-"object.  The size to copy, 'n', is always measured in bytes.\n"
-"\n"
-"Unlike other methods, this one supports all Python buffer including\n"
-"byte strings and bytearrays---but it still does not support\n"
-"non-contiguous buffers.");
-
-#define ffi_memmove  b_memmove     /* ffi_memmove() => b_memmove()
-                                      from _cffi_backend.c */
-
-PyDoc_STRVAR(ffi_init_once_doc,
-"init_once(function, tag): run function() once.  More precisely,\n"
-"'function()' is called the first time we see a given 'tag'.\n"
-"\n"
-"The return value of function() is remembered and returned by the current\n"
-"and all future init_once() with the same tag.  If init_once() is called\n"
-"from multiple threads in parallel, all calls block until the execution\n"
-"of function() is done.  If function() raises an exception, it is\n"
-"propagated and nothing is cached.");
-
-#if PY_MAJOR_VERSION < 3
-/* PyCapsule_New is redefined to be PyCObject_FromVoidPtr in _cffi_backend,
-   which gives 2.6 compatibility; but the destructor signature is different */
-static void _free_init_once_lock(void *lock)
-{
-    PyThread_free_lock((PyThread_type_lock)lock);
-}
-#else
-static void _free_init_once_lock(PyObject *capsule)
-{
-    PyThread_type_lock lock;
-    lock = PyCapsule_GetPointer(capsule, "cffi_init_once_lock");
-    if (lock != NULL)
-        PyThread_free_lock(lock);
-}
-#endif
-
-static PyObject *ffi_init_once(FFIObject *self, PyObject *args, PyObject *kwds)
-{
-    static char *keywords[] = {"func", "tag", NULL};
-    PyObject *cache, *func, *tag, *tup, *res, *x, *lockobj;
-    PyThread_type_lock lock;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", keywords, &func, &tag))
-        return NULL;
-
-    /* a lot of fun with reference counting and error checking
-       in this function */
-
-    /* atomically get or create a new dict (no GIL release) */
-    cache = self->init_once_cache;
-    if (cache == NULL) {
-        cache = PyDict_New();
-        if (cache == NULL)
-            return NULL;
-        self->init_once_cache = cache;
-    }
-
-    /* get the tuple from cache[tag], or make a new one: (False, lock) */
-    tup = PyDict_GetItem(cache, tag);
-    if (tup == NULL) {
-        lock = PyThread_allocate_lock();
-        if (lock == NULL)
-            return NULL;
-        x = PyCapsule_New(lock, "cffi_init_once_lock", _free_init_once_lock);
-        if (x == NULL) {
-            PyThread_free_lock(lock);
-            return NULL;
-        }
-        tup = PyTuple_Pack(2, Py_False, x);
-        Py_DECREF(x);
-        if (tup == NULL)
-            return NULL;
-        x = tup;
-
-        /* Possible corner case if 'tag' is an object overriding __eq__
-           in pure Python: the GIL may be released when we are running it.
-           We really need to call dict.setdefault(). */
-        tup = PyObject_CallMethod(cache, "setdefault", "OO", tag, x);
-        Py_DECREF(x);
-        if (tup == NULL)
-            return NULL;
-
-        Py_DECREF(tup);   /* there is still a ref inside the dict */
-    }
-
-    res = PyTuple_GET_ITEM(tup, 1);
-    Py_INCREF(res);
-
-    if (PyTuple_GET_ITEM(tup, 0) == Py_True) {
-        /* tup == (True, result): return the result. */
-        return res;
-    }
-
-    /* tup == (False, lock) */
-    lockobj = res;
-    lock = (PyThread_type_lock)PyCapsule_GetPointer(lockobj,
-                                                    "cffi_init_once_lock");
-    if (lock == NULL) {
-        Py_DECREF(lockobj);
-        return NULL;
-    }
-
-    Py_BEGIN_ALLOW_THREADS
-    PyThread_acquire_lock(lock, WAIT_LOCK);
-    Py_END_ALLOW_THREADS
-
-    x = PyDict_GetItem(cache, tag);
-    if (x != NULL && PyTuple_GET_ITEM(x, 0) == Py_True) {
-        /* the real result was put in the dict while we were waiting
-           for PyThread_acquire_lock() above */
-        res = PyTuple_GET_ITEM(x, 1);
-        Py_INCREF(res);
-    }
-    else {
-        res = PyObject_CallFunction(func, "");
-        if (res != NULL) {
-            tup = PyTuple_Pack(2, Py_True, res);
-            if (tup == NULL || PyDict_SetItem(cache, tag, tup) < 0) {
-                Py_DECREF(res);
-                res = NULL;
-            }
-            Py_XDECREF(tup);
-        }
-    }
-
-    PyThread_release_lock(lock);
-    Py_DECREF(lockobj);
-    return res;
-}
-
-PyDoc_STRVAR(ffi_release_doc,
-"Release now the resources held by a 'cdata' object from ffi.new(),\n"
-"ffi.gc() or ffi.from_buffer().  The cdata object must not be used\n"
-"afterwards.\n"
-"\n"
-"'ffi.release(cdata)' is equivalent to 'cdata.__exit__()'.\n"
-"\n"
-"Note that on CPython this method has no effect (so far) on objects\n"
-"returned by ffi.new(), because the memory is allocated inline with the\n"
-"cdata object and cannot be freed independently.  It might be fixed in\n"
-"future releases of cffi.");
-
-#define ffi_release  b_release     /* ffi_release() => b_release()
-                                      from _cffi_backend.c */
-
-
-#define METH_VKW  (METH_VARARGS | METH_KEYWORDS)
-static PyMethodDef ffi_methods[] = {
- {"addressof",  (PyCFunction)ffi_addressof,  METH_VARARGS, ffi_addressof_doc},
- {"alignof",    (PyCFunction)ffi_alignof,    METH_O,       ffi_alignof_doc},
- {"def_extern", (PyCFunction)ffi_def_extern, METH_VKW,     ffi_def_extern_doc},
- {"callback",   (PyCFunction)ffi_callback,   METH_VKW,     ffi_callback_doc},
- {"cast",       (PyCFunction)ffi_cast,       METH_VARARGS, ffi_cast_doc},
- {"dlclose",    (PyCFunction)ffi_dlclose,    METH_VARARGS, ffi_dlclose_doc},
- {"dlopen",     (PyCFunction)ffi_dlopen,     METH_VARARGS, ffi_dlopen_doc},
- {"from_buffer",(PyCFunction)ffi_from_buffer,METH_VKW,     ffi_from_buffer_doc},
- {"from_handle",(PyCFunction)ffi_from_handle,METH_O,       ffi_from_handle_doc},
- {"gc",         (PyCFunction)ffi_gc,         METH_VKW,     ffi_gc_doc},
- {"getctype",   (PyCFunction)ffi_getctype,   METH_VKW,     ffi_getctype_doc},
-#ifdef MS_WIN32
- {"getwinerror",(PyCFunction)ffi_getwinerror,METH_VKW,     ffi_getwinerror_doc},
-#endif
- {"init_once",  (PyCFunction)ffi_init_once,  METH_VKW,     ffi_init_once_doc},
- {"integer_const",(PyCFunction)ffi_int_const,METH_VKW,     ffi_int_const_doc},
- {"list_types", (PyCFunction)ffi_list_types, METH_NOARGS,  ffi_list_types_doc},
- {"memmove",    (PyCFunction)ffi_memmove,    METH_VKW,     ffi_memmove_doc},
- {"new",        (PyCFunction)ffi_new,        METH_VKW,     ffi_new_doc},
-{"new_allocator",(PyCFunction)ffi_new_allocator,METH_VKW,ffi_new_allocator_doc},
- {"new_handle", (PyCFunction)ffi_new_handle, METH_O,       ffi_new_handle_doc},
- {"offsetof",   (PyCFunction)ffi_offsetof,   METH_VARARGS, ffi_offsetof_doc},
- {"release",    (PyCFunction)ffi_release,    METH_O,       ffi_release_doc},
- {"sizeof",     (PyCFunction)ffi_sizeof,     METH_O,       ffi_sizeof_doc},
- {"string",     (PyCFunction)ffi_string,     METH_VKW,     ffi_string_doc},
- {"typeof",     (PyCFunction)ffi_typeof,     METH_O,       ffi_typeof_doc},
- {"unpack",     (PyCFunction)ffi_unpack,     METH_VKW,     ffi_unpack_doc},
- {NULL}
-};
-
-static PyGetSetDef ffi_getsets[] = {
-    {"errno",  ffi_get_errno,  ffi_set_errno,  ffi_errno_doc},
-    {NULL}
-};
-
-static PyTypeObject FFI_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.FFI",
-    sizeof(FFIObject),
-    0,
-    (destructor)ffi_dealloc,                    /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_compare */
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    PyObject_GenericGetAttr,                    /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-        Py_TPFLAGS_BASETYPE,                    /* tp_flags */
-    0,                                          /* tp_doc */
-    (traverseproc)ffi_traverse,                 /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    ffi_methods,                                /* tp_methods */
-    0,                                          /* tp_members */
-    ffi_getsets,                                /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    ffiobj_init,                                /* tp_init */
-    0,                                          /* tp_alloc */
-    ffiobj_new,                                 /* tp_new */
-    PyObject_GC_Del,                            /* tp_free */
-};
-
-
-static PyObject *
-_fetch_external_struct_or_union(const struct _cffi_struct_union_s *s,
-                                PyObject *included_ffis, int recursion)
-{
-    Py_ssize_t i;
-
-    if (included_ffis == NULL)
-        return NULL;
-
-    if (recursion > 100) {
-        PyErr_SetString(PyExc_RuntimeError,
-                        "recursion overflow in ffi.include() delegations");
-        return NULL;
-    }
-
-    for (i = 0; i < PyTuple_GET_SIZE(included_ffis); i++) {
-        FFIObject *ffi1;
-        const struct _cffi_struct_union_s *s1;
-        int sindex;
-        PyObject *x;
-
-        ffi1 = (FFIObject *)PyTuple_GET_ITEM(included_ffis, i);
-        sindex = search_in_struct_unions(&ffi1->types_builder.ctx, s->name,
-                                         strlen(s->name));
-        if (sindex < 0)  /* not found at all */
-            continue;
-        s1 = &ffi1->types_builder.ctx.struct_unions[sindex];
-        if ((s1->flags & (_CFFI_F_EXTERNAL | _CFFI_F_UNION))
-                == (s->flags & _CFFI_F_UNION)) {
-            /* s1 is not external, and the same kind (struct or union) as s */
-            return _realize_c_struct_or_union(&ffi1->types_builder, sindex);
-        }
-        /* not found, look more recursively */
-        x = _fetch_external_struct_or_union(
-                s, ffi1->types_builder.included_ffis, recursion + 1);
-        if (x != NULL || PyErr_Occurred())
-            return x;   /* either found, or got an error */
-    }
-    return NULL;   /* not found at all, leave without an error */
-}
diff --git a/c/file_emulator.h b/c/file_emulator.h
deleted file mode 100644
index 82a34c0..0000000
--- a/c/file_emulator.h
+++ /dev/null
@@ -1,93 +0,0 @@
-
-/* Emulation of PyFile_Check() and PyFile_AsFile() for Python 3. */
-
-static PyObject *PyIOBase_TypeObj;
-
-static int init_file_emulator(void)
-{
-    if (PyIOBase_TypeObj == NULL) {
-        PyObject *io = PyImport_ImportModule("_io");
-        if (io == NULL)
-            return -1;
-        PyIOBase_TypeObj = PyObject_GetAttrString(io, "_IOBase");
-        if (PyIOBase_TypeObj == NULL)
-            return -1;
-    }
-    return 0;
-}
-
-
-#define PyFile_Check(p)  PyObject_IsInstance(p, PyIOBase_TypeObj)
-
-
-static void _close_file_capsule(PyObject *ob_capsule)
-{
-    FILE *f = (FILE *)PyCapsule_GetPointer(ob_capsule, "FILE");
-    if (f != NULL)
-        fclose(f);
-}
-
-
-static FILE *PyFile_AsFile(PyObject *ob_file)
-{
-    PyObject *ob, *ob_capsule = NULL, *ob_mode = NULL;
-    FILE *f;
-    int fd;
-    const char *mode;
-
-    ob = PyObject_CallMethod(ob_file, "flush", NULL);
-    if (ob == NULL)
-        goto fail;
-    Py_DECREF(ob);
-
-    ob_capsule = PyObject_GetAttrString(ob_file, "__cffi_FILE");
-    if (ob_capsule == NULL) {
-        PyErr_Clear();
-
-        fd = PyObject_AsFileDescriptor(ob_file);
-        if (fd < 0)
-            goto fail;
-
-        ob_mode = PyObject_GetAttrString(ob_file, "mode");
-        if (ob_mode == NULL)
-            goto fail;
-        mode = PyText_AsUTF8(ob_mode);
-        if (mode == NULL)
-            goto fail;
-
-        fd = dup(fd);
-        if (fd < 0) {
-            PyErr_SetFromErrno(PyExc_OSError);
-            goto fail;
-        }
-
-        f = fdopen(fd, mode);
-        if (f == NULL) {
-            close(fd);
-            PyErr_SetFromErrno(PyExc_OSError);
-            goto fail;
-        }
-        setbuf(f, NULL);    /* non-buffered */
-        Py_DECREF(ob_mode);
-        ob_mode = NULL;
-
-        ob_capsule = PyCapsule_New(f, "FILE", _close_file_capsule);
-        if (ob_capsule == NULL) {
-            fclose(f);
-            goto fail;
-        }
-
-        if (PyObject_SetAttrString(ob_file, "__cffi_FILE", ob_capsule) < 0)
-            goto fail;
-    }
-    else {
-        f = PyCapsule_GetPointer(ob_capsule, "FILE");
-    }
-    Py_DECREF(ob_capsule);   /* assumes still at least one reference */
-    return f;
-
- fail:
-    Py_XDECREF(ob_mode);
-    Py_XDECREF(ob_capsule);
-    return NULL;
-}
diff --git a/c/lib_obj.c b/c/lib_obj.c
deleted file mode 100644
index 38bf3d5..0000000
--- a/c/lib_obj.c
+++ /dev/null
@@ -1,716 +0,0 @@
-
-/* A Lib object is what is in the "lib" attribute of a C extension
-   module originally created by recompile().
-
-   A Lib object is special in the sense that it has a custom
-   __getattr__ which returns C globals, functions and constants.  The
-   original idea was to raise AttributeError for anything else, even
-   attrs like '__class__', but it breaks various things; now, standard
-   attrs are returned, but in the unlikely case where a user cdef()s
-   the same name, then the standard attr is hidden (and the various
-   things like introspection might break).
-
-   A Lib object has got a reference to the _cffi_type_context_s
-   structure, which is used to create lazily the objects returned by
-   __getattr__.
-*/
-
-struct CPyExtFunc_s {
-    PyMethodDef md;
-    void *direct_fn;
-    int type_index;
-    char doc[1];
-};
-
-struct LibObject_s {
-    PyObject_HEAD
-    builder_c_t *l_types_builder; /* same as the one on the ffi object */
-    PyObject *l_dict;           /* content, built lazily */
-    PyObject *l_libname;        /* some string that gives the name of the lib */
-    FFIObject *l_ffi;           /* reference back to the ffi object */
-    void *l_libhandle;          /* the dlopen()ed handle, if any */
-    int l_auto_close;           /* if we must dlclose() this handle */
-};
-
-static struct CPyExtFunc_s *_cpyextfunc_get(PyObject *x)
-{
-    PyObject *y;
-    LibObject *lo;
-    PyCFunctionObject *fo;
-
-    if (!PyCFunction_Check(x))
-        return NULL;
-    y = PyCFunction_GET_SELF(x);
-    if (!LibObject_Check(y))
-        return NULL;
-
-    fo = (PyCFunctionObject *)x;
-    lo = (LibObject *)y;
-    if (lo->l_libname != fo->m_module)
-        return NULL;
-
-    return (struct CPyExtFunc_s *)(fo->m_ml);
-}
-
-static PyObject *_cpyextfunc_type(LibObject *lib, struct CPyExtFunc_s *exf)
-{
-    PyObject *tuple, *result;
-    tuple = realize_c_type_or_func(lib->l_types_builder,
-                                   lib->l_types_builder->ctx.types,
-                                   exf->type_index);
-    if (tuple == NULL)
-        return NULL;
-
-    /* 'tuple' is a tuple of length 1 containing the real CT_FUNCTIONPTR
-       object */
-    result = PyTuple_GetItem(tuple, 0);
-    Py_XINCREF(result);
-    Py_DECREF(tuple);
-    return result;
-}
-
-static PyObject *_cpyextfunc_type_index(PyObject *x)
-{
-    struct CPyExtFunc_s *exf;
-    LibObject *lib;
-
-    assert(PyErr_Occurred());
-    exf = _cpyextfunc_get(x);
-    if (exf == NULL)
-        return NULL;    /* still the same exception is set */
-
-    PyErr_Clear();
-
-    lib = (LibObject *)PyCFunction_GET_SELF(x);
-    return _cpyextfunc_type(lib, exf);
-}
-
-static void cdlopen_close_ignore_errors(void *libhandle);  /* forward */
-static void *cdlopen_fetch(PyObject *libname, void *libhandle,
-                           const char *symbol);
-
-static void lib_dealloc(LibObject *lib)
-{
-    PyObject_GC_UnTrack(lib);
-    if (lib->l_auto_close)
-        cdlopen_close_ignore_errors(lib->l_libhandle);
-    Py_DECREF(lib->l_dict);
-    Py_DECREF(lib->l_libname);
-    Py_DECREF(lib->l_ffi);
-    PyObject_GC_Del(lib);
-}
-
-static int lib_traverse(LibObject *lib, visitproc visit, void *arg)
-{
-    Py_VISIT(lib->l_dict);
-    Py_VISIT(lib->l_libname);
-    Py_VISIT(lib->l_ffi);
-    return 0;
-}
-
-static PyObject *lib_repr(LibObject *lib)
-{
-    return PyText_FromFormat("<Lib object for '%.200s'>",
-                             PyText_AS_UTF8(lib->l_libname));
-}
-
-static PyObject *lib_build_cpython_func(LibObject *lib,
-                                        const struct _cffi_global_s *g,
-                                        const char *s, int flags)
-{
-    /* First make sure the argument types and return type are really
-       built.  The C extension code can then assume that they are,
-       by calling _cffi_type().
-    */
-    PyObject *result = NULL;
-    CTypeDescrObject **pfargs = NULL;
-    CTypeDescrObject *fresult;
-    Py_ssize_t nargs = 0;
-    struct CPyExtFunc_s *xfunc;
-    int i, type_index = _CFFI_GETARG(g->type_op);
-    _cffi_opcode_t *opcodes = lib->l_types_builder->ctx.types;
-    static const char *const format = ";\n\nCFFI C function from %s.lib";
-    const char *libname = PyText_AS_UTF8(lib->l_libname);
-    struct funcbuilder_s funcbuilder;
-
-    /* return type: */
-    fresult = realize_c_func_return_type(lib->l_types_builder, opcodes,
-                                       type_index);
-    if (fresult == NULL)
-        goto error;
-
-    /* argument types: */
-    /* note that if the arguments are already built, they have a
-       pointer in the 'opcodes' array, and GETOP() returns a
-       random even value.  But OP_FUNCTION_END is odd, so the
-       condition below still works correctly. */
-    i = type_index + 1;
-    while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END)
-        i++;
-    pfargs = alloca(sizeof(CTypeDescrObject *) * (i - type_index - 1));
-    i = type_index + 1;
-    while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END) {
-        CTypeDescrObject *ct = realize_c_type(lib->l_types_builder, opcodes, i);
-        if (ct == NULL)
-            goto error;
-        pfargs[nargs++] = ct;
-        i++;
-    }
-
-    memset(&funcbuilder, 0, sizeof(funcbuilder));
-    if (fb_build_name(&funcbuilder, g->name, pfargs, nargs, fresult, 0) < 0)
-        goto error;
-
-    /* The few bytes of memory we allocate here appear to leak, but
-       this is not a real leak.  Indeed, CPython never unloads its C
-       extension modules.  There is only one PyMem_Malloc() per real
-       C function in a CFFI C extension module.  That means that this
-       PyMem_Malloc() could also have been written with a static
-       global variable generated for each CPYTHON_BLTN defined in the
-       C extension, and the effect would be the same (but a bit more
-       complicated).
-    */
-    xfunc = PyMem_Malloc(sizeof(struct CPyExtFunc_s) +
-                         funcbuilder.nb_bytes +
-                         strlen(format) + strlen(libname));
-    if (xfunc == NULL) {
-        PyErr_NoMemory();
-        goto error;
-    }
-    memset((char *)xfunc, 0, sizeof(struct CPyExtFunc_s));
-    assert(g->address);
-    xfunc->md.ml_meth = (PyCFunction)g->address;
-    xfunc->md.ml_flags = flags;
-    xfunc->md.ml_name = g->name;
-    xfunc->md.ml_doc = xfunc->doc;
-    xfunc->direct_fn = g->size_or_direct_fn;
-    xfunc->type_index = type_index;
-
-    /* build the docstring */
-    funcbuilder.bufferp = xfunc->doc;
-    if (fb_build_name(&funcbuilder, g->name, pfargs, nargs, fresult, 0) < 0)
-        goto error;
-    sprintf(funcbuilder.bufferp - 1, format, libname);
-    /* done building the docstring */
-
-    result = PyCFunction_NewEx(&xfunc->md, (PyObject *)lib, lib->l_libname);
-    /* fall-through */
- error:
-    Py_XDECREF(fresult);
-    while (nargs > 0) {
-        --nargs;
-        Py_DECREF(pfargs[nargs]);
-    }
-    return result;
-}
-
-static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name,
-                                          int recursion)
-{
-    /* does not return a new reference! */
-    PyObject *x;
-    int index;
-    const struct _cffi_global_s *g;
-    CTypeDescrObject *ct;
-    builder_c_t *types_builder = lib->l_types_builder;
-    const char *s = PyText_AsUTF8(name);
-    if (s == NULL)
-        return NULL;
-
-    index = search_in_globals(&types_builder->ctx, s, strlen(s));
-    if (index < 0) {
-
-        if (types_builder->included_libs != NULL) {
-            Py_ssize_t i;
-            PyObject *included_ffis = types_builder->included_ffis;
-            PyObject *included_libs = types_builder->included_libs;
-
-            if (recursion > 100) {
-                PyErr_SetString(PyExc_RuntimeError,
-                    "recursion overflow in ffi.include() delegations");
-                return NULL;
-            }
-
-            for (i = 0; i < PyTuple_GET_SIZE(included_libs); i++) {
-                LibObject *lib1;
-
-                lib1 = (LibObject *)PyTuple_GET_ITEM(included_libs, i);
-                if (lib1 != NULL) {
-                    x = PyDict_GetItem(lib1->l_dict, name);
-                    if (x != NULL) {
-                        Py_INCREF(x);
-                        goto found;
-                    }
-                    x = lib_build_and_cache_attr(lib1, name, recursion + 1);
-                    if (x != NULL) {
-                        Py_INCREF(x);
-                        goto found;
-                    }
-                }
-                else {
-                    FFIObject *ffi1;
-
-                    ffi1 = (FFIObject *)PyTuple_GetItem(included_ffis, i);
-                    if (ffi1 == NULL)
-                        return NULL;
-                    x = ffi_fetch_int_constant(ffi1, s, recursion + 1);
-                    if (x != NULL)
-                        goto found;
-                }
-                if (PyErr_Occurred())
-                    return NULL;
-            }
-        }
-
-        if (recursion > 0)
-            return NULL;  /* no error set, continue looking elsewhere */
-
-        PyErr_Format(PyExc_AttributeError,
-                     "cffi library '%.200s' has no function, constant "
-                     "or global variable named '%.200s'",
-                     PyText_AS_UTF8(lib->l_libname), s);
-        return NULL;
-    }
-
-    g = &types_builder->ctx.globals[index];
-
-    switch (_CFFI_GETOP(g->type_op)) {
-
-    case _CFFI_OP_CPYTHON_BLTN_V:
-        x = lib_build_cpython_func(lib, g, s, METH_VARARGS);
-        break;
-
-    case _CFFI_OP_CPYTHON_BLTN_N:
-        x = lib_build_cpython_func(lib, g, s, METH_NOARGS);
-        break;
-
-    case _CFFI_OP_CPYTHON_BLTN_O:
-        x = lib_build_cpython_func(lib, g, s, METH_O);
-        break;
-
-    case _CFFI_OP_CONSTANT_INT:
-    case _CFFI_OP_ENUM:
-    {
-        /* a constant integer whose value, in an "unsigned long long",
-           is obtained by calling the function at g->address */
-        x = realize_global_int(types_builder, index);
-        break;
-    }
-
-    case _CFFI_OP_CONSTANT:
-    case _CFFI_OP_DLOPEN_CONST:
-    {
-        /* a constant which is not of integer type */
-        char *data;
-        ct = realize_c_type(types_builder, types_builder->ctx.types,
-                            _CFFI_GETARG(g->type_op));
-        if (ct == NULL)
-            return NULL;
-
-        if (ct->ct_size <= 0) {
-            PyErr_Format(FFIError, "constant '%s' is of type '%s', "
-                         "whose size is not known", s, ct->ct_name);
-            return NULL;
-        }
-        if (g->address == NULL) {
-            /* for dlopen() style */
-            assert(_CFFI_GETOP(g->type_op) == _CFFI_OP_DLOPEN_CONST);
-            data = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
-            if (data == NULL)
-                return NULL;
-        }
-        else {
-            /* The few bytes of memory we allocate here appear to leak, but
-               this is not a real leak.  Indeed, CPython never unloads its C
-               extension modules.  There is only one PyMem_Malloc() per real
-               non-integer C constant in a CFFI C extension module.  That
-               means that this PyMem_Malloc() could also have been written
-               with a static global variable generated for each OP_CONSTANT
-               defined in the C extension, and the effect would be the same
-               (but a bit more complicated).
-
-               Note that we used to do alloca(), but see issue #198.  We
-               could still do alloca(), or explicit PyMem_Free(), in some
-               cases; but there is no point and it only makes the remaining
-               less-common cases more suspicious.
-            */
-            assert(_CFFI_GETOP(g->type_op) == _CFFI_OP_CONSTANT);
-            data = PyMem_Malloc(ct->ct_size);
-            if (data == NULL) {
-                PyErr_NoMemory();
-                return NULL;
-            }
-            ((void(*)(char*))g->address)(data);
-        }
-        x = convert_to_object(data, ct);
-        Py_DECREF(ct);
-        break;
-    }
-
-    case _CFFI_OP_GLOBAL_VAR:
-    {
-        /* global variable of the exact type specified here
-           (nowadays, only used by the ABI mode or backward
-           compatibility; see _CFFI_OP_GLOBAL_VAR_F for the API mode)
-         */
-        Py_ssize_t g_size = (Py_ssize_t)g->size_or_direct_fn;
-        ct = realize_c_type(types_builder, types_builder->ctx.types,
-                            _CFFI_GETARG(g->type_op));
-        if (ct == NULL)
-            return NULL;
-        if (g_size != ct->ct_size && g_size != 0 && ct->ct_size > 0) {
-            PyErr_Format(FFIError,
-                         "global variable '%.200s' should be %zd bytes "
-                         "according to the cdef, but is actually %zd",
-                         s, ct->ct_size, g_size);
-            x = NULL;
-        }
-        else {
-            void *address = g->address;
-            if (address == NULL) {
-                /* for dlopen() style */
-                address = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
-                if (address == NULL)
-                    return NULL;
-            }
-            x = make_global_var(name, ct, address, NULL);
-        }
-        Py_DECREF(ct);
-        break;
-    }
-
-    case _CFFI_OP_GLOBAL_VAR_F:
-        ct = realize_c_type(types_builder, types_builder->ctx.types,
-                            _CFFI_GETARG(g->type_op));
-        if (ct == NULL)
-            return NULL;
-        x = make_global_var(name, ct, NULL, (gs_fetch_addr_fn)g->address);
-        Py_DECREF(ct);
-        break;
-
-    case _CFFI_OP_DLOPEN_FUNC:
-    {
-        /* For dlopen(): the function of the given 'name'.  We use
-           dlsym() to get the address of something in the dynamic
-           library, which we interpret as being exactly a function of
-           the specified type.
-        */
-        PyObject *ct1;
-        void *address = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
-        if (address == NULL)
-            return NULL;
-
-        ct1 = realize_c_type_or_func(types_builder,
-                                     types_builder->ctx.types,
-                                     _CFFI_GETARG(g->type_op));
-        if (ct1 == NULL)
-            return NULL;
-
-        assert(!CTypeDescr_Check(ct1));   /* must be a function */
-        x = new_simple_cdata(address, unwrap_fn_as_fnptr(ct1));
-
-        Py_DECREF(ct1);
-        break;
-    }
-
-    case _CFFI_OP_EXTERN_PYTHON:
-        /* for reading 'lib.bar' where bar is declared with extern "Python" */
-        ct = realize_c_type(types_builder, types_builder->ctx.types,
-                            _CFFI_GETARG(g->type_op));
-        if (ct == NULL)
-            return NULL;
-        x = convert_to_object((char *)&g->size_or_direct_fn, ct);
-        Py_DECREF(ct);
-        break;
-
-    default:
-        PyErr_Format(PyExc_NotImplementedError, "in lib_build_attr: op=%d",
-                     (int)_CFFI_GETOP(g->type_op));
-        return NULL;
-    }
-
- found:
-    if (x != NULL) {
-        int err = PyDict_SetItem(lib->l_dict, name, x);
-        Py_DECREF(x);
-        if (err < 0)     /* else there is still one ref left in the dict */
-            return NULL;
-    }
-    return x;
-}
-
-#define LIB_GET_OR_CACHE_ADDR(x, lib, name, error)      \
-    do {                                                \
-        x = PyDict_GetItem(lib->l_dict, name);          \
-        if (x == NULL) {                                \
-            x = lib_build_and_cache_attr(lib, name, 0); \
-            if (x == NULL) {                            \
-                error;                                  \
-            }                                           \
-        }                                               \
-    } while (0)
-
-static PyObject *_lib_dir1(LibObject *lib, int ignore_global_vars)
-{
-    const struct _cffi_global_s *g = lib->l_types_builder->ctx.globals;
-    int i, count = 0, total = lib->l_types_builder->ctx.num_globals;
-    PyObject *s, *lst = PyList_New(total);
-    if (lst == NULL)
-        return NULL;
-
-    for (i = 0; i < total; i++) {
-        if (ignore_global_vars) {
-            int op = _CFFI_GETOP(g[i].type_op);
-            if (op == _CFFI_OP_GLOBAL_VAR || op == _CFFI_OP_GLOBAL_VAR_F)
-                continue;
-        }
-        s = PyText_FromString(g[i].name);
-        if (s == NULL)
-            goto error;
-        PyList_SET_ITEM(lst, count, s);
-        count++;
-    }
-    if (PyList_SetSlice(lst, count, total, NULL) < 0)
-        goto error;
-    return lst;
-
- error:
-    Py_DECREF(lst);
-    return NULL;
-}
-
-static PyObject *_lib_dict(LibObject *lib)
-{
-    const struct _cffi_global_s *g = lib->l_types_builder->ctx.globals;
-    int i, total = lib->l_types_builder->ctx.num_globals;
-    PyObject *name, *x, *d = PyDict_New();
-    if (d == NULL)
-        return NULL;
-
-    for (i = 0; i < total; i++) {
-        name = PyText_FromString(g[i].name);
-        if (name == NULL)
-            goto error;
-
-        LIB_GET_OR_CACHE_ADDR(x, lib, name, goto error);
-
-        if (PyDict_SetItem(d, name, x) < 0)
-            goto error;
-        Py_DECREF(name);
-    }
-    return d;
-
- error:
-    Py_XDECREF(name);
-    Py_DECREF(d);
-    return NULL;
-}
-
-static PyObject *lib_getattr(LibObject *lib, PyObject *name)
-{
-    const char *p;
-    PyObject *x;
-    LIB_GET_OR_CACHE_ADDR(x, lib, name, goto missing);
-
-    if (GlobSupport_Check(x)) {
-        return read_global_var((GlobSupportObject *)x);
-    }
-    Py_INCREF(x);
-    return x;
-
- missing:
-    /*** ATTRIBUTEERROR IS SET HERE ***/
-    p = PyText_AsUTF8(name);
-    if (p == NULL)
-        return NULL;
-    if (strcmp(p, "__all__") == 0) {
-        PyErr_Clear();
-        return _lib_dir1(lib, 1);
-    }
-    if (strcmp(p, "__dict__") == 0) {
-        PyErr_Clear();
-        return _lib_dict(lib);
-    }
-    if (strcmp(p, "__class__") == 0) {
-        PyErr_Clear();
-        x = (PyObject *)&PyModule_Type;
-        /* ^^^ used to be Py_TYPE(lib).  But HAAAAAACK!  That makes
-           help() behave correctly.  I couldn't find a more reasonable
-           way.  Urgh. */
-        Py_INCREF(x);
-        return x;
-    }
-    /* this hack is for Python 3.5, and also to give a more 
-       module-like behavior */
-    if (strcmp(p, "__name__") == 0) {
-        PyErr_Clear();
-        return PyText_FromFormat("%s.lib", PyText_AS_UTF8(lib->l_libname));
-    }
-#if PY_MAJOR_VERSION >= 3
-    if (strcmp(p, "__loader__") == 0 || strcmp(p, "__spec__") == 0) {
-        /* some more module-like behavior hacks */
-        PyErr_Clear();
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-#endif
-    return NULL;
-}
-
-static int lib_setattr(LibObject *lib, PyObject *name, PyObject *val)
-{
-    PyObject *x;
-    LIB_GET_OR_CACHE_ADDR(x, lib, name, return -1);
-
-    if (val == NULL) {
-        PyErr_SetString(PyExc_AttributeError, "C attribute cannot be deleted");
-        return -1;
-    }
-
-    if (GlobSupport_Check(x)) {
-        return write_global_var((GlobSupportObject *)x, val);
-    }
-
-    PyErr_Format(PyExc_AttributeError,
-                 "cannot write to function or constant '%.200s'",
-                 PyText_Check(name) ? PyText_AS_UTF8(name) : "?");
-    return -1;
-}
-
-static PyObject *lib_dir(PyObject *self, PyObject *noarg)
-{
-    return _lib_dir1((LibObject *)self, 0);
-}
-
-static PyMethodDef lib_methods[] = {
-    {"__dir__",   lib_dir,  METH_NOARGS},
-    {NULL,        NULL}           /* sentinel */
-};
-
-static PyTypeObject Lib_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.Lib",
-    sizeof(LibObject),
-    0,
-    (destructor)lib_dealloc,                    /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_compare */
-    (reprfunc)lib_repr,                         /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    (getattrofunc)lib_getattr,                  /* tp_getattro */
-    (setattrofunc)lib_setattr,                  /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
-    0,                                          /* tp_doc */
-    (traverseproc)lib_traverse,                 /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    lib_methods,                                /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    offsetof(LibObject, l_dict),                /* tp_dictoffset */
-};
-
-static LibObject *lib_internal_new(FFIObject *ffi, const char *module_name,
-                                   void *dlopen_libhandle, int auto_close)
-{
-    LibObject *lib;
-    PyObject *libname, *dict;
-
-    libname = PyText_FromString(module_name);
-    if (libname == NULL)
-        goto err1;
-
-    dict = PyDict_New();
-    if (dict == NULL)
-        goto err2;
-
-    lib = (LibObject *)PyType_GenericAlloc(&Lib_Type, 0);
-    if (lib == NULL)
-        goto err3;
-
-    lib->l_types_builder = &ffi->types_builder;
-    lib->l_dict = dict;
-    lib->l_libname = libname;
-    Py_INCREF(ffi);
-    lib->l_ffi = ffi;
-    lib->l_libhandle = dlopen_libhandle;
-    lib->l_auto_close = auto_close;
-    return lib;
-
- err3:
-    Py_DECREF(dict);
- err2:
-    Py_DECREF(libname);
- err1:
-    if (auto_close)
-        cdlopen_close_ignore_errors(dlopen_libhandle);
-    return NULL;
-}
-
-static PyObject *address_of_global_var(PyObject *args)
-{
-    LibObject *lib;
-    PyObject *x, *o_varname;
-    char *varname;
-
-    if (!PyArg_ParseTuple(args, "O!s", &Lib_Type, &lib, &varname))
-        return NULL;
-
-    /* rebuild a string from 'varname', to do typechecks and to force
-       a unicode back to a plain string (on python 2) */
-    o_varname = PyText_FromString(varname);
-    if (o_varname == NULL)
-        return NULL;
-
-    LIB_GET_OR_CACHE_ADDR(x, lib, o_varname, goto error);
-    Py_DECREF(o_varname);
-    if (GlobSupport_Check(x)) {
-        return cg_addressof_global_var((GlobSupportObject *)x);
-    }
-    else {
-        struct CPyExtFunc_s *exf = _cpyextfunc_get(x);
-        if (exf != NULL) {  /* an OP_CPYTHON_BLTN: '&func' returns a cdata */
-            PyObject *ct;
-            if (exf->direct_fn == NULL) {
-                Py_INCREF(x);    /* backward compatibility */
-                return x;
-            }
-            ct = _cpyextfunc_type(lib, exf);
-            if (ct == NULL)
-                return NULL;
-            x = new_simple_cdata(exf->direct_fn, (CTypeDescrObject *)ct);
-            Py_DECREF(ct);
-            return x;
-        }
-        if (CData_Check(x) &&  /* a constant functionptr cdata: 'f == &f' */
-                (((CDataObject *)x)->c_type->ct_flags & CT_FUNCTIONPTR) != 0) {
-            Py_INCREF(x);
-            return x;
-        }
-        else {
-            PyErr_Format(PyExc_AttributeError,
-                         "cannot take the address of the constant '%.200s'",
-                         varname);
-            return NULL;
-        }
-    }
-
- error:
-    Py_DECREF(o_varname);
-    return NULL;
-}
diff --git a/c/libffi_arm64/README b/c/libffi_arm64/README
deleted file mode 100644
index 3b8f133..0000000
--- a/c/libffi_arm64/README
+++ /dev/null
@@ -1,5 +0,0 @@
-Libffi package for ARM64 is copied from cpython binary dependencies
-
-https://github.com/python/cpython-bin-deps/archive/libffi.zip
-
-The library file has been renamed from libffi-7.lib to ffi.lib to avoid special casing
\ No newline at end of file
diff --git a/c/libffi_arm64/ffi.lib b/c/libffi_arm64/ffi.lib
deleted file mode 100644
index 4a8b84b..0000000
--- a/c/libffi_arm64/ffi.lib
+++ /dev/null
Binary files differ
diff --git a/c/libffi_arm64/include/ffi.h b/c/libffi_arm64/include/ffi.h
deleted file mode 100644
index d91c3e1..0000000
--- a/c/libffi_arm64/include/ffi.h
+++ /dev/null
@@ -1,515 +0,0 @@
-/* -----------------------------------------------------------------*-C-*-
-   libffi 3.3-rc0 - Copyright (c) 2011, 2014 Anthony Green
-                    - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
-
-   Permission is hereby granted, free of charge, to any person
-   obtaining a copy of this software and associated documentation
-   files (the ``Software''), to deal in the Software without
-   restriction, including without limitation the rights to use, copy,
-   modify, merge, publish, distribute, sublicense, and/or sell copies
-   of the Software, and to permit persons to whom the Software is
-   furnished to do so, subject to the following conditions:
-
-   The above copyright notice and this permission notice shall be
-   included in all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-   DEALINGS IN THE SOFTWARE.
-
-   ----------------------------------------------------------------------- */
-
-/* -------------------------------------------------------------------
-   Most of the API is documented in doc/libffi.texi.
-
-   The raw API is designed to bypass some of the argument packing and
-   unpacking on architectures for which it can be avoided.  Routines
-   are provided to emulate the raw API if the underlying platform
-   doesn't allow faster implementation.
-
-   More details on the raw API can be found in:
-
-   http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
-
-   and
-
-   http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
-   -------------------------------------------------------------------- */
-
-#ifndef LIBFFI_H
-#define LIBFFI_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Specify which architecture libffi is configured for. */
-#ifndef ARM_WIN64
-#define ARM_WIN64
-#endif
-
-/* ---- System configuration information --------------------------------- */
-
-#include <ffitarget.h>
-
-#ifndef LIBFFI_ASM
-
-#if defined(_MSC_VER) && !defined(__clang__)
-#define __attribute__(X)
-#endif
-
-#include <stddef.h>
-#include <limits.h>
-
-/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
-   But we can find it either under the correct ANSI name, or under GNU
-   C's internal name.  */
-
-#define FFI_64_BIT_MAX 9223372036854775807
-
-#ifdef LONG_LONG_MAX
-# define FFI_LONG_LONG_MAX LONG_LONG_MAX
-#else
-# ifdef LLONG_MAX
-#  define FFI_LONG_LONG_MAX LLONG_MAX
-#  ifdef _AIX52 /* or newer has C99 LLONG_MAX */
-#   undef FFI_64_BIT_MAX
-#   define FFI_64_BIT_MAX 9223372036854775807LL
-#  endif /* _AIX52 or newer */
-# else
-#  ifdef __GNUC__
-#   define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
-#  endif
-#  ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
-#   ifndef __PPC64__
-#    if defined (__IBMC__) || defined (__IBMCPP__)
-#     define FFI_LONG_LONG_MAX LONGLONG_MAX
-#    endif
-#   endif /* __PPC64__ */
-#   undef  FFI_64_BIT_MAX
-#   define FFI_64_BIT_MAX 9223372036854775807LL
-#  endif
-# endif
-#endif
-
-/* The closure code assumes that this works on pointers, i.e. a size_t
-   can hold a pointer.  */
-
-typedef struct _ffi_type
-{
-  size_t size;
-  unsigned short alignment;
-  unsigned short type;
-  struct _ffi_type **elements;
-} ffi_type;
-
-/* Need minimal decorations for DLLs to work on Windows.  GCC has
-   autoimport and autoexport.  Always mark externally visible symbols
-   as dllimport for MSVC clients, even if it means an extra indirection
-   when using the static version of the library.
-   Besides, as a workaround, they can define FFI_BUILDING if they
-   *know* they are going to link with the static library.  */
-#if defined _MSC_VER
-# if defined FFI_BUILDING_DLL /* Building libffi.DLL with msvcc.sh */
-#  define FFI_API __declspec(dllexport)
-# elif !defined FFI_BUILDING  /* Importing libffi.DLL */
-#  define FFI_API __declspec(dllimport)
-# else                        /* Building/linking static library */
-#  define FFI_API
-# endif
-#else
-# define FFI_API
-#endif
-
-/* The externally visible type declarations also need the MSVC DLL
-   decorations, or they will not be exported from the object file.  */
-#if defined LIBFFI_HIDE_BASIC_TYPES
-# define FFI_EXTERN FFI_API
-#else
-# define FFI_EXTERN extern FFI_API
-#endif
-
-#ifndef LIBFFI_HIDE_BASIC_TYPES
-#if SCHAR_MAX == 127
-# define ffi_type_uchar                ffi_type_uint8
-# define ffi_type_schar                ffi_type_sint8
-#else
- #error "char size not supported"
-#endif
-
-#if SHRT_MAX == 32767
-# define ffi_type_ushort       ffi_type_uint16
-# define ffi_type_sshort       ffi_type_sint16
-#elif SHRT_MAX == 2147483647
-# define ffi_type_ushort       ffi_type_uint32
-# define ffi_type_sshort       ffi_type_sint32
-#else
- #error "short size not supported"
-#endif
-
-#if INT_MAX == 32767
-# define ffi_type_uint         ffi_type_uint16
-# define ffi_type_sint         ffi_type_sint16
-#elif INT_MAX == 2147483647
-# define ffi_type_uint         ffi_type_uint32
-# define ffi_type_sint         ffi_type_sint32
-#elif INT_MAX == 9223372036854775807
-# define ffi_type_uint         ffi_type_uint64
-# define ffi_type_sint         ffi_type_sint64
-#else
- #error "int size not supported"
-#endif
-
-#if LONG_MAX == 2147483647
-# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
- #error "no 64-bit data type supported"
-# endif
-#elif LONG_MAX != FFI_64_BIT_MAX
- #error "long size not supported"
-#endif
-
-#if LONG_MAX == 2147483647
-# define ffi_type_ulong        ffi_type_uint32
-# define ffi_type_slong        ffi_type_sint32
-#elif LONG_MAX == FFI_64_BIT_MAX
-# define ffi_type_ulong        ffi_type_uint64
-# define ffi_type_slong        ffi_type_sint64
-#else
- #error "long size not supported"
-#endif
-
-/* These are defined in types.c.  */
-FFI_EXTERN ffi_type ffi_type_void;
-FFI_EXTERN ffi_type ffi_type_uint8;
-FFI_EXTERN ffi_type ffi_type_sint8;
-FFI_EXTERN ffi_type ffi_type_uint16;
-FFI_EXTERN ffi_type ffi_type_sint16;
-FFI_EXTERN ffi_type ffi_type_uint32;
-FFI_EXTERN ffi_type ffi_type_sint32;
-FFI_EXTERN ffi_type ffi_type_uint64;
-FFI_EXTERN ffi_type ffi_type_sint64;
-FFI_EXTERN ffi_type ffi_type_float;
-FFI_EXTERN ffi_type ffi_type_double;
-FFI_EXTERN ffi_type ffi_type_pointer;
-
-#if 0
-FFI_EXTERN ffi_type ffi_type_longdouble;
-#else
-#define ffi_type_longdouble ffi_type_double
-#endif
-
-#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
-FFI_EXTERN ffi_type ffi_type_complex_float;
-FFI_EXTERN ffi_type ffi_type_complex_double;
-#if 0
-FFI_EXTERN ffi_type ffi_type_complex_longdouble;
-#else
-#define ffi_type_complex_longdouble ffi_type_complex_double
-#endif
-#endif
-#endif /* LIBFFI_HIDE_BASIC_TYPES */
-
-typedef enum {
-  FFI_OK = 0,
-  FFI_BAD_TYPEDEF,
-  FFI_BAD_ABI
-} ffi_status;
-
-typedef struct {
-  ffi_abi abi;
-  unsigned nargs;
-  ffi_type **arg_types;
-  ffi_type *rtype;
-  unsigned bytes;
-  unsigned flags;
-#ifdef FFI_EXTRA_CIF_FIELDS
-  FFI_EXTRA_CIF_FIELDS;
-#endif
-} ffi_cif;
-
-/* ---- Definitions for the raw API -------------------------------------- */
-
-#ifndef FFI_SIZEOF_ARG
-# if LONG_MAX == 2147483647
-#  define FFI_SIZEOF_ARG        4
-# elif LONG_MAX == FFI_64_BIT_MAX
-#  define FFI_SIZEOF_ARG        8
-# endif
-#endif
-
-#ifndef FFI_SIZEOF_JAVA_RAW
-#  define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
-#endif
-
-typedef union {
-  ffi_sarg  sint;
-  ffi_arg   uint;
-  float	    flt;
-  char      data[FFI_SIZEOF_ARG];
-  void*     ptr;
-} ffi_raw;
-
-#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
-/* This is a special case for mips64/n32 ABI (and perhaps others) where
-   sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8.  */
-typedef union {
-  signed int	sint;
-  unsigned int	uint;
-  float		flt;
-  char		data[FFI_SIZEOF_JAVA_RAW];
-  void*		ptr;
-} ffi_java_raw;
-#else
-typedef ffi_raw ffi_java_raw;
-#endif
-
-
-FFI_API 
-void ffi_raw_call (ffi_cif *cif,
-		   void (*fn)(void),
-		   void *rvalue,
-		   ffi_raw *avalue);
-
-FFI_API void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
-FFI_API void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
-FFI_API size_t ffi_raw_size (ffi_cif *cif);
-
-/* This is analogous to the raw API, except it uses Java parameter
-   packing, even on 64-bit machines.  I.e. on 64-bit machines longs
-   and doubles are followed by an empty 64-bit word.  */
-
-#if !FFI_NATIVE_RAW_API
-FFI_API
-void ffi_java_raw_call (ffi_cif *cif,
-			void (*fn)(void),
-			void *rvalue,
-			ffi_java_raw *avalue);
-#endif
-
-FFI_API
-void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
-FFI_API
-void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
-FFI_API
-size_t ffi_java_raw_size (ffi_cif *cif);
-
-/* ---- Definitions for closures ----------------------------------------- */
-
-#if FFI_CLOSURES
-
-#ifdef _MSC_VER
-__declspec(align(8))
-#endif
-typedef struct {
-#if 0
-  void *trampoline_table;
-  void *trampoline_table_entry;
-#else
-  char tramp[FFI_TRAMPOLINE_SIZE];
-#endif
-  ffi_cif   *cif;
-  void     (*fun)(ffi_cif*,void*,void**,void*);
-  void      *user_data;
-} ffi_closure
-#ifdef __GNUC__
-    __attribute__((aligned (8)))
-#endif
-    ;
-
-#ifndef __GNUC__
-# ifdef __sgi
-#  pragma pack 0
-# endif
-#endif
-
-FFI_API void *ffi_closure_alloc (size_t size, void **code);
-FFI_API void ffi_closure_free (void *);
-
-FFI_API ffi_status
-ffi_prep_closure (ffi_closure*,
-		  ffi_cif *,
-		  void (*fun)(ffi_cif*,void*,void**,void*),
-		  void *user_data)
-#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 405)
-  __attribute__((deprecated ("use ffi_prep_closure_loc instead")))
-#elif defined(__GNUC__) && __GNUC__ >= 3
-  __attribute__((deprecated))
-#endif
-  ;
-
-FFI_API ffi_status
-ffi_prep_closure_loc (ffi_closure*,
-		      ffi_cif *,
-		      void (*fun)(ffi_cif*,void*,void**,void*),
-		      void *user_data,
-		      void*codeloc);
-
-#ifdef __sgi
-# pragma pack 8
-#endif
-typedef struct {
-#if 0
-  void *trampoline_table;
-  void *trampoline_table_entry;
-#else
-  char tramp[FFI_TRAMPOLINE_SIZE];
-#endif
-  ffi_cif   *cif;
-
-#if !FFI_NATIVE_RAW_API
-
-  /* If this is enabled, then a raw closure has the same layout 
-     as a regular closure.  We use this to install an intermediate 
-     handler to do the transaltion, void** -> ffi_raw*.  */
-
-  void     (*translate_args)(ffi_cif*,void*,void**,void*);
-  void      *this_closure;
-
-#endif
-
-  void     (*fun)(ffi_cif*,void*,ffi_raw*,void*);
-  void      *user_data;
-
-} ffi_raw_closure;
-
-typedef struct {
-#if 0
-  void *trampoline_table;
-  void *trampoline_table_entry;
-#else
-  char tramp[FFI_TRAMPOLINE_SIZE];
-#endif
-
-  ffi_cif   *cif;
-
-#if !FFI_NATIVE_RAW_API
-
-  /* If this is enabled, then a raw closure has the same layout 
-     as a regular closure.  We use this to install an intermediate 
-     handler to do the translation, void** -> ffi_raw*.  */
-
-  void     (*translate_args)(ffi_cif*,void*,void**,void*);
-  void      *this_closure;
-
-#endif
-
-  void     (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
-  void      *user_data;
-
-} ffi_java_raw_closure;
-
-FFI_API ffi_status
-ffi_prep_raw_closure (ffi_raw_closure*,
-		      ffi_cif *cif,
-		      void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-		      void *user_data);
-
-FFI_API ffi_status
-ffi_prep_raw_closure_loc (ffi_raw_closure*,
-			  ffi_cif *cif,
-			  void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-			  void *user_data,
-			  void *codeloc);
-
-#if !FFI_NATIVE_RAW_API
-FFI_API ffi_status
-ffi_prep_java_raw_closure (ffi_java_raw_closure*,
-		           ffi_cif *cif,
-		           void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
-		           void *user_data);
-
-FFI_API ffi_status
-ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
-			       ffi_cif *cif,
-			       void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
-			       void *user_data,
-			       void *codeloc);
-#endif
-
-#endif /* FFI_CLOSURES */
-
-#if FFI_GO_CLOSURES
-
-typedef struct {
-  void      *tramp;
-  ffi_cif   *cif;
-  void     (*fun)(ffi_cif*,void*,void**,void*);
-} ffi_go_closure;
-
-FFI_API ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
-				void (*fun)(ffi_cif*,void*,void**,void*));
-
-FFI_API void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
-		  void **avalue, void *closure);
-
-#endif /* FFI_GO_CLOSURES */
-
-/* ---- Public interface definition -------------------------------------- */
-
-FFI_API 
-ffi_status ffi_prep_cif(ffi_cif *cif,
-			ffi_abi abi,
-			unsigned int nargs,
-			ffi_type *rtype,
-			ffi_type **atypes);
-
-FFI_API
-ffi_status ffi_prep_cif_var(ffi_cif *cif,
-			    ffi_abi abi,
-			    unsigned int nfixedargs,
-			    unsigned int ntotalargs,
-			    ffi_type *rtype,
-			    ffi_type **atypes);
-
-FFI_API
-void ffi_call(ffi_cif *cif,
-	      void (*fn)(void),
-	      void *rvalue,
-	      void **avalue);
-
-FFI_API
-ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,
-				   size_t *offsets);
-
-/* Useful for eliminating compiler warnings.  */
-#define FFI_FN(f) ((void (*)(void))f)
-
-/* ---- Definitions shared with assembly code ---------------------------- */
-
-#endif
-
-/* If these change, update src/mips/ffitarget.h. */
-#define FFI_TYPE_VOID       0    
-#define FFI_TYPE_INT        1
-#define FFI_TYPE_FLOAT      2    
-#define FFI_TYPE_DOUBLE     3
-#if 0
-#define FFI_TYPE_LONGDOUBLE 4
-#else
-#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
-#endif
-#define FFI_TYPE_UINT8      5   
-#define FFI_TYPE_SINT8      6
-#define FFI_TYPE_UINT16     7 
-#define FFI_TYPE_SINT16     8
-#define FFI_TYPE_UINT32     9
-#define FFI_TYPE_SINT32     10
-#define FFI_TYPE_UINT64     11
-#define FFI_TYPE_SINT64     12
-#define FFI_TYPE_STRUCT     13
-#define FFI_TYPE_POINTER    14
-#define FFI_TYPE_COMPLEX    15
-
-/* This should always refer to the last type code (for sanity checks).  */
-#define FFI_TYPE_LAST       FFI_TYPE_COMPLEX
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/c/libffi_arm64/include/fficonfig.h b/c/libffi_arm64/include/fficonfig.h
deleted file mode 100644
index 5768c29..0000000
--- a/c/libffi_arm64/include/fficonfig.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/* fficonfig.h.  Generated from fficonfig.h.in by configure.  */
-/* fficonfig.h.in.  Generated from configure.ac by autoheader.  */
-
-/* Define if building universal (internal helper macro) */
-/* #undef AC_APPLE_UNIVERSAL_BUILD */
-
-/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
-   systems. This function is required for `alloca.c' support on those systems.
-   */
-/* #undef CRAY_STACKSEG_END */
-
-/* Define to 1 if using `alloca.c'. */
-/* #undef C_ALLOCA */
-
-/* Define to the flags needed for the .section .eh_frame directive. */
-/* #undef EH_FRAME_FLAGS */
-
-/* Define this if you want extra debugging. */
-/* #undef FFI_DEBUG */
-
-/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
-/* #undef FFI_EXEC_TRAMPOLINE_TABLE */
-
-/* Define this if you want to enable pax emulated trampolines */
-/* #undef FFI_MMAP_EXEC_EMUTRAMP_PAX */
-
-/* Cannot use malloc on this target, so, we revert to alternative means */
-/* #undef FFI_MMAP_EXEC_WRIT */
-
-/* Define this if you do not want support for the raw API. */
-/* #undef FFI_NO_RAW_API */
-
-/* Define this if you do not want support for aggregate types. */
-/* #undef FFI_NO_STRUCTS */
-
-/* Define to 1 if you have `alloca', as a function or macro. */
-#define HAVE_ALLOCA 1
-
-/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
-   */
-/* #undef HAVE_ALLOCA_H */
-
-/* Define if your assembler supports .cfi_* directives. */
-/* #undef HAVE_AS_CFI_PSEUDO_OP */
-
-/* Define if your assembler supports .register. */
-/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
-
-/* Define if the compiler uses zarch features. */
-/* #undef HAVE_AS_S390_ZARCH */
-
-/* Define if your assembler and linker support unaligned PC relative relocs.
-   */
-/* #undef HAVE_AS_SPARC_UA_PCREL */
-
-/* Define if your assembler supports unwind section type. */
-/* #undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE */
-
-/* Define if your assembler supports PC relative relocs. */
-/* #undef HAVE_AS_X86_PCREL */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-/* #undef HAVE_DLFCN_H */
-
-/* Define if __attribute__((visibility("hidden"))) is supported. */
-/* #undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define if you have the long double type and it is bigger than a double */
-/* #undef HAVE_LONG_DOUBLE */
-
-/* Define if you support more than one size of the long double type */
-/* #undef HAVE_LONG_DOUBLE_VARIANT */
-
-/* Define to 1 if you have the `memcpy' function. */
-/* #undef HAVE_MEMCPY */
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `mkostemp' function. */
-/* #undef HAVE_MKOSTEMP */
-
-/* Define to 1 if you have the `mmap' function. */
-/* #undef HAVE_MMAP */
-
-/* Define if mmap with MAP_ANON(YMOUS) works. */
-/* #undef HAVE_MMAP_ANON */
-
-/* Define if mmap of /dev/zero works. */
-/* #undef HAVE_MMAP_DEV_ZERO */
-
-/* Define if read-only mmap of a plain file works. */
-/* #undef HAVE_MMAP_FILE */
-
-/* Define if .eh_frame sections should be read-only. */
-/* #undef HAVE_RO_EH_FRAME */
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-/* #undef HAVE_STRINGS_H */
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <sys/mman.h> header file. */
-/* #undef HAVE_SYS_MMAN_H */
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-/* #undef HAVE_UNISTD_H */
-
-/* Define to 1 if GNU symbol versioning is used for libatomic. */
-/* #undef LIBFFI_GNU_SYMBOL_VERSIONING */
-
-/* Define to the sub-directory where libtool stores uninstalled libraries. */
-#define LT_OBJDIR ".libs/"
-
-/* Name of package */
-#define PACKAGE "libffi"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "http://github.com/libffi/libffi/issues"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "libffi"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "libffi 3.3-rc0"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libffi"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "3.3-rc0"
-
-/* The size of `double', as computed by sizeof. */
-#define SIZEOF_DOUBLE 8
-
-/* The size of `long double', as computed by sizeof. */
-#define SIZEOF_LONG_DOUBLE 8
-
-/* The size of `size_t', as computed by sizeof. */
-#define SIZEOF_SIZE_T 8
-
-/* If using the C implementation of alloca, define if you know the
-   direction of stack growth for your system; otherwise it will be
-   automatically deduced at runtime.
-	STACK_DIRECTION > 0 => grows toward higher addresses
-	STACK_DIRECTION < 0 => grows toward lower addresses
-	STACK_DIRECTION = 0 => direction of growth unknown */
-/* #undef STACK_DIRECTION */
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define if symbols are underscored. */
-/* #undef SYMBOL_UNDERSCORE */
-
-/* Define this if you are using Purify and want to suppress spurious messages.
-   */
-/* #undef USING_PURIFY */
-
-/* Version number of package */
-#define VERSION "3.3-rc0"
-
-/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
-   significant byte first (like Motorola and SPARC, unlike Intel). */
-#if defined AC_APPLE_UNIVERSAL_BUILD
-# if defined __BIG_ENDIAN__
-#  define WORDS_BIGENDIAN 1
-# endif
-#else
-# ifndef WORDS_BIGENDIAN
-/* #  undef WORDS_BIGENDIAN */
-# endif
-#endif
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef size_t */
-
-
-#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
-#ifdef LIBFFI_ASM
-#ifdef __APPLE__
-#define FFI_HIDDEN(name) .private_extern name
-#else
-#define FFI_HIDDEN(name) .hidden name
-#endif
-#else
-#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
-#endif
-#else
-#ifdef LIBFFI_ASM
-#define FFI_HIDDEN(name)
-#else
-#define FFI_HIDDEN
-#endif
-#endif
-
diff --git a/c/libffi_arm64/include/ffitarget.h b/c/libffi_arm64/include/ffitarget.h
deleted file mode 100644
index ecb6d2d..0000000
--- a/c/libffi_arm64/include/ffitarget.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-``Software''), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
-
-#ifndef LIBFFI_TARGET_H
-#define LIBFFI_TARGET_H
-
-#ifndef LIBFFI_H
-#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
-#endif
-
-#ifndef LIBFFI_ASM
-#ifdef __ILP32__
-#define FFI_SIZEOF_ARG 8
-#define FFI_SIZEOF_JAVA_RAW  4
-typedef unsigned long long ffi_arg;
-typedef signed long long ffi_sarg;
-#elif defined(_M_ARM64)
-#define FFI_SIZEOF_ARG 8
-typedef unsigned long long ffi_arg;
-typedef signed long long ffi_sarg;
-#else
-typedef unsigned long ffi_arg;
-typedef signed long ffi_sarg;
-#endif
-
-typedef enum ffi_abi
-  {
-    FFI_FIRST_ABI = 0,
-    FFI_SYSV,
-    FFI_LAST_ABI,
-    FFI_DEFAULT_ABI = FFI_SYSV
-  } ffi_abi;
-#endif
-
-/* ---- Definitions for closures ----------------------------------------- */
-
-#define FFI_CLOSURES 1
-#define FFI_NATIVE_RAW_API 0
-
-#if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE
-
-#ifdef __MACH__
-#define FFI_TRAMPOLINE_SIZE 16
-#define FFI_TRAMPOLINE_CLOSURE_OFFSET 16
-#else
-#error "No trampoline table implementation"
-#endif
-
-#else
-#define FFI_TRAMPOLINE_SIZE 24
-#define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE
-#endif
-
-#ifdef _M_ARM64
-#define FFI_EXTRA_CIF_FIELDS unsigned is_variadic
-#endif
-
-/* ---- Internal ---- */
-
-#if defined (__APPLE__)
-#define FFI_TARGET_SPECIFIC_VARIADIC
-#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs
-#elif !defined(_M_ARM64)
-/* iOS and Windows reserve x18 for the system.  Disable Go closures until
-   a new static chain is chosen.  */
-#define FFI_GO_CLOSURES 1
-#endif
-
-#ifndef _M_ARM64
-/* No complex type on Windows */
-#define FFI_TARGET_HAS_COMPLEX_TYPE
-#endif
-
-#endif
diff --git a/c/libffi_x86_x64/LICENSE b/c/libffi_x86_x64/LICENSE
deleted file mode 100644
index f591795..0000000
--- a/c/libffi_x86_x64/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-libffi - Copyright (c) 1996-2003  Red Hat, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-``Software''), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
diff --git a/c/libffi_x86_x64/README b/c/libffi_x86_x64/README
deleted file mode 100644
index 97a12cf..0000000
--- a/c/libffi_x86_x64/README
+++ /dev/null
@@ -1,502 +0,0 @@
-This directory contains the libffi package, which is not part of GCC but
-shipped with GCC as convenience.
-
-Copied without changes from CPython 2.7 head (e04e1f253ed8).
-
-Status
-======
-
-libffi-2.00 has not been released yet! This is a development snapshot!
-
-libffi-1.20 was released on October 5, 1998. Check the libffi web
-page for updates: <URL:http://sources.redhat.com/libffi/>.
-
-
-What is libffi?
-===============
-
-Compilers for high level languages generate code that follow certain
-conventions. These conventions are necessary, in part, for separate
-compilation to work. One such convention is the "calling
-convention". The "calling convention" is essentially a set of
-assumptions made by the compiler about where function arguments will
-be found on entry to a function. A "calling convention" also specifies
-where the return value for a function is found.
-
-Some programs may not know at the time of compilation what arguments
-are to be passed to a function. For instance, an interpreter may be
-told at run-time about the number and types of arguments used to call
-a given function. Libffi can be used in such programs to provide a
-bridge from the interpreter program to compiled code.
-
-The libffi library provides a portable, high level programming
-interface to various calling conventions. This allows a programmer to
-call any function specified by a call interface description at run
-time.  
-
-Ffi stands for Foreign Function Interface. A foreign function
-interface is the popular name for the interface that allows code
-written in one language to call code written in another language. The
-libffi library really only provides the lowest, machine dependent
-layer of a fully featured foreign function interface. A layer must
-exist above libffi that handles type conversions for values passed
-between the two languages.
-
-
-Supported Platforms and Prerequisites
-=====================================
-
-Libffi has been ported to:
-
-	SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9)
-
-	Irix 5.3 & 6.2 (System V/o32 & n32)
-
-	Intel x86 - Linux (System V ABI)
-
-	Alpha - Linux and OSF/1
-
-	m68k - Linux (System V ABI)
-
-	PowerPC - Linux (System V ABI, Darwin, AIX)
-
-	ARM - Linux (System V ABI)
-
-Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are
-that other versions will work.  Libffi has also been built and tested
-with the SGI compiler tools.
-
-On PowerPC, the tests failed (see the note below).
-
-You must use GNU make to build libffi. SGI's make will not work.
-Sun's probably won't either.
-	
-If you port libffi to another platform, please let me know! I assume
-that some will be easy (x86 NetBSD), and others will be more difficult
-(HP).
-
-
-Installing libffi
-=================
-
-[Note: before actually performing any of these installation steps,
- you may wish to read the "Platform Specific Notes" below.]
-
-First you must configure the distribution for your particular
-system. Go to the directory you wish to build libffi in and run the
-"configure" program found in the root directory of the libffi source
-distribution.
-
-You may want to tell configure where to install the libffi library and
-header files. To do that, use the --prefix configure switch.  Libffi
-will install under /usr/local by default. 
-
-If you want to enable extra run-time debugging checks use the the
---enable-debug configure switch. This is useful when your program dies
-mysteriously while using libffi. 
-
-Another useful configure switch is --enable-purify-safety. Using this
-will add some extra code which will suppress certain warnings when you
-are using Purify with libffi. Only use this switch when using 
-Purify, as it will slow down the library.
-
-Configure has many other options. Use "configure --help" to see them all.
-
-Once configure has finished, type "make". Note that you must be using
-GNU make. SGI's make will not work.  Sun's probably won't either.
-You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
-
-To ensure that libffi is working as advertised, type "make test".
-
-To install the library and header files, type "make install".
-
-
-Using libffi
-============
-
-	The Basics
-	----------
-
-Libffi assumes that you have a pointer to the function you wish to
-call and that you know the number and types of arguments to pass it,
-as well as the return type of the function.
-
-The first thing you must do is create an ffi_cif object that matches
-the signature of the function you wish to call. The cif in ffi_cif
-stands for Call InterFace. To prepare a call interface object, use the
-following function:
-
-ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi,
-			unsigned int nargs, 
-			ffi_type *rtype, ffi_type **atypes);
-
-	CIF is a pointer to the call interface object you wish
-		to initialize.
-
-	ABI is an enum that specifies the calling convention 
-		to use for the call. FFI_DEFAULT_ABI defaults
-		to the system's native calling convention. Other
-		ABI's may be used with care. They are system
-		specific.
-
-	NARGS is the number of arguments this function accepts.	
-		libffi does not yet support vararg functions.
-
-	RTYPE is a pointer to an ffi_type structure that represents
-		the return type of the function. Ffi_type objects
-		describe the types of values. libffi provides
-		ffi_type objects for many of the native C types:
-		signed int, unsigned int, signed char, unsigned char,
-		etc. There is also a pointer ffi_type object and
-		a void ffi_type. Use &ffi_type_void for functions that 
-		don't return values.
-
-	ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long.
-		If NARGS is 0, this is ignored.
-
-
-ffi_prep_cif will return a status code that you are responsible 
-for checking. It will be one of the following:
-
-	FFI_OK - All is good.
-
-	FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif
-		came across is bad.
-
-
-Before making the call, the VALUES vector should be initialized 
-with pointers to the appropriate argument values.
-
-To call the the function using the initialized ffi_cif, use the
-ffi_call function:
-
-void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues);
-
-	CIF is a pointer to the ffi_cif initialized specifically
-		for this function.
-
-	FN is a pointer to the function you want to call.
-
-	RVALUE is a pointer to a chunk of memory that is to hold the
-		result of the function call. Currently, it must be
-		at least one word in size (except for the n32 version
-		under Irix 6.x, which must be a pointer to an 8 byte 
-		aligned value (a long long). It must also be at least 
-		word aligned (depending on the return type, and the
-		system's alignment requirements). If RTYPE is 
-		&ffi_type_void, this is ignored. If RVALUE is NULL, 
-		the return value is discarded.
-
-	AVALUES is a vector of void* that point to the memory locations
-		holding the argument values for a call.
-		If NARGS is 0, this is ignored.
-
-
-If you are expecting a return value from FN it will have been stored
-at RVALUE.
-
-
-
-	An Example
-	----------
-
-Here is a trivial example that calls puts() a few times.
-
-    #include <stdio.h>
-    #include <ffi.h>
-    
-    int main()
-    {
-      ffi_cif cif;
-      ffi_type *args[1];
-      void *values[1];
-      char *s;
-      int rc;
-      
-      /* Initialize the argument info vectors */    
-      args[0] = &ffi_type_uint;
-      values[0] = &s;
-      
-      /* Initialize the cif */
-      if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
-    		       &ffi_type_uint, args) == FFI_OK)
-        {
-          s = "Hello World!";
-          ffi_call(&cif, puts, &rc, values);
-          /* rc now holds the result of the call to puts */
-          
-          /* values holds a pointer to the function's arg, so to 
-	     call puts() again all we need to do is change the 
-             value of s */
-          s = "This is cool!";
-          ffi_call(&cif, puts, &rc, values);
-        }
-      
-      return 0;
-    }
-
-
-
-	Aggregate Types
-	---------------
-
-Although libffi has no special support for unions or bit-fields, it is
-perfectly happy passing structures back and forth. You must first
-describe the structure to libffi by creating a new ffi_type object
-for it. Here is the definition of ffi_type:
-
-    typedef struct _ffi_type
-    {
-      unsigned size;
-      short alignment;
-      short type;
-      struct _ffi_type **elements;
-    } ffi_type;
-    
-All structures must have type set to FFI_TYPE_STRUCT.  You may set
-size and alignment to 0. These will be calculated and reset to the
-appropriate values by ffi_prep_cif().
-
-elements is a NULL terminated array of pointers to ffi_type objects
-that describe the type of the structure elements. These may, in turn,
-be structure elements.
-
-The following example initializes a ffi_type object representing the
-tm struct from Linux's time.h:
-
-				    struct tm {
-					int tm_sec;
-					int tm_min;
-					int tm_hour;
-					int tm_mday;
-					int tm_mon;
-					int tm_year;
-					int tm_wday;
-					int tm_yday;
-					int tm_isdst;
-					/* Those are for future use. */
-					long int __tm_gmtoff__;
-					__const char *__tm_zone__;
-				    };
-
-    {
-      ffi_type tm_type;
-      ffi_type *tm_type_elements[12];
-      int i;
-
-      tm_type.size = tm_type.alignment = 0;
-      tm_type.elements = &tm_type_elements;
-    
-      for (i = 0; i < 9; i++)
-          tm_type_elements[i] = &ffi_type_sint;
-
-      tm_type_elements[9] = &ffi_type_slong;
-      tm_type_elements[10] = &ffi_type_pointer;
-      tm_type_elements[11] = NULL;
-
-      /* tm_type can now be used to represent tm argument types and
-	 return types for ffi_prep_cif() */
-    }
-
-
-
-Platform Specific Notes
-=======================
-
-	Intel x86
-	---------
-
-There are no known problems with the x86 port.
-
-	Sun SPARC - SunOS 4.1.3 & Solaris 2.x
-	-------------------------------------
-
-You must use GNU Make to build libffi on Sun platforms.
-
-	MIPS - Irix 5.3 & 6.x
-	---------------------
-
-Irix 6.2 and better supports three different calling conventions: o32,
-n32 and n64. Currently, libffi only supports both o32 and n32 under
-Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be
-configured for whichever calling convention it was built for.
-
-By default, the configure script will try to build libffi with the GNU
-development tools. To build libffi with the SGI development tools, set
-the environment variable CC to either "cc -32" or "cc -n32" before
-running configure under Irix 6.x (depending on whether you want an o32
-or n32 library), or just "cc" for Irix 5.3.
-
-With the n32 calling convention, when returning structures smaller
-than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned.
-Here's one way of forcing this:
-
-	double struct_storage[2];
-	my_small_struct *s = (my_small_struct *) struct_storage;  
-	/* Use s for RVALUE */
-
-If you don't do this you are liable to get spurious bus errors. 
-
-"long long" values are not supported yet.
-
-You must use GNU Make to build libffi on SGI platforms.
-
-	ARM - System V ABI
-	------------------
-
-The ARM port was performed on a NetWinder running ARM Linux ELF
-(2.0.31) and gcc 2.8.1.
-
-
-
-	PowerPC System V ABI
-	--------------------
-
-There are two `System V ABI's which libffi implements for PowerPC.
-They differ only in how small structures are returned from functions.
-
-In the FFI_SYSV version, structures that are 8 bytes or smaller are
-returned in registers.  This is what GCC does when it is configured
-for solaris, and is what the System V ABI I have (dated September
-1995) says.
-
-In the FFI_GCC_SYSV version, all structures are returned the same way:
-by passing a pointer as the first argument to the function.  This is
-what GCC does when it is configured for linux or a generic sysv
-target.
-
-EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a
-inconsistency with the SysV ABI: When a procedure is called with many
-floating-point arguments, some of them get put on the stack.  They are
-all supposed to be stored in double-precision format, even if they are
-only single-precision, but EGCS stores single-precision arguments as
-single-precision anyway.  This causes one test to fail (the `many
-arguments' test).
-
-
-What's With The Crazy Comments?
-===============================
-
-You might notice a number of cryptic comments in the code, delimited
-by /*@ and @*/. These are annotations read by the program LCLint, a
-tool for statically checking C programs. You can read all about it at
-<http://larch-www.lcs.mit.edu:8001/larch/lclint/index.html>.
-
-
-History
-=======
-
-1.20 Oct-5-98
-	Raffaele Sena produces ARM port.
-
-1.19 Oct-5-98
-	Fixed x86 long double and long long return support.
-	m68k bug fixes from Andreas Schwab.
-	Patch for DU assembler compatibility for the Alpha from Richard
-	Henderson.
-
-1.18 Apr-17-98
-	Bug fixes and MIPS configuration changes.
-
-1.17 Feb-24-98
-	Bug fixes and m68k port from Andreas Schwab. PowerPC port from
-	Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
-
-1.16 Feb-11-98
-	Richard Henderson produces Alpha port.
-
-1.15 Dec-4-97
-	Fixed an n32 ABI bug. New libtool, auto* support.
-
-1.14 May-13-97
-	libtool is now used to generate shared and static libraries.
-	Fixed a minor portability problem reported by Russ McManus
-	<mcmanr@eq.gs.com>.
-
-1.13 Dec-2-96
-	Added --enable-purify-safety to keep Purify from complaining
-	about certain low level code.
-	Sparc fix for calling functions with < 6 args.
-	Linux x86 a.out fix.
-
-1.12 Nov-22-96
-	Added missing ffi_type_void, needed for supporting void return 
-	types. Fixed test case for non MIPS machines. Cygnus Support 
-	is now Cygnus Solutions. 
-
-1.11 Oct-30-96
-	Added notes about GNU make.
-
-1.10 Oct-29-96
-	Added configuration fix for non GNU compilers.
-
-1.09 Oct-29-96
-	Added --enable-debug configure switch. Clean-ups based on LCLint 
-	feedback. ffi_mips.h is always installed. Many configuration 
-	fixes. Fixed ffitest.c for sparc builds.
-
-1.08 Oct-15-96
-	Fixed n32 problem. Many clean-ups.
-
-1.07 Oct-14-96
-	Gordon Irlam rewrites v8.S again. Bug fixes.
-
-1.06 Oct-14-96
-	Gordon Irlam improved the sparc port. 
-
-1.05 Oct-14-96
-	Interface changes based on feedback.
-
-1.04 Oct-11-96
-	Sparc port complete (modulo struct passing bug).
-
-1.03 Oct-10-96
-	Passing struct args, and returning struct values works for
-	all architectures/calling conventions. Expanded tests.
-
-1.02 Oct-9-96
-	Added SGI n32 support. Fixed bugs in both o32 and Linux support.
-	Added "make test".
-
-1.01 Oct-8-96
-	Fixed float passing bug in mips version. Restructured some
-	of the code. Builds cleanly with SGI tools.
-
-1.00 Oct-7-96
-	First release. No public announcement.
-
-
-Authors & Credits
-=================
-
-libffi was written by Anthony Green <green@cygnus.com>.
-
-Portions of libffi were derived from Gianni Mariani's free gencall
-library for Silicon Graphics machines.
-
-The closure mechanism was designed and implemented by Kresten Krab
-Thorup.
-
-The Sparc port was derived from code contributed by the fine folks at
-Visible Decisions Inc <http://www.vdi.com>. Further enhancements were
-made by Gordon Irlam at Cygnus Solutions <http://www.cygnus.com>.
-
-The Alpha port was written by Richard Henderson at Cygnus Solutions.
-
-Andreas Schwab ported libffi to m68k Linux and provided a number of
-bug fixes.
-
-Geoffrey Keating ported libffi to the PowerPC.
-
-Raffaele Sena ported libffi to the ARM.
-
-Jesper Skov and Andrew Haley both did more than their fair share of
-stepping through the code and tracking down bugs.
-
-Thanks also to Tom Tromey for bug fixes and configuration help.
-
-Thanks to Jim Blandy, who provided some useful feedback on the libffi
-interface.
-
-If you have a problem, or have found a bug, please send a note to
-green@cygnus.com.
diff --git a/c/libffi_x86_x64/README.ctypes b/c/libffi_x86_x64/README.ctypes
deleted file mode 100644
index 17e8a40..0000000
--- a/c/libffi_x86_x64/README.ctypes
+++ /dev/null
@@ -1,7 +0,0 @@
-The purpose is to hack the libffi sources so that they can be compiled
-with MSVC, and to extend them so that they have the features I need
-for ctypes.
-
-I retrieved the libffi sources from the gcc cvs repository on
-2004-01-27.  Then I did 'configure' in a 'build' subdirectory on a x86
-linux system, and copied the files I found useful.
diff --git a/c/libffi_x86_x64/ffi.c b/c/libffi_x86_x64/ffi.c
deleted file mode 100644
index b9e324f..0000000
--- a/c/libffi_x86_x64/ffi.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/* -----------------------------------------------------------------------
-   ffi.c - Copyright (c) 1996, 1998, 1999, 2001  Red Hat, Inc.
-           Copyright (c) 2002  Ranjit Mathew
-           Copyright (c) 2002  Bo Thorsen
-           Copyright (c) 2002  Roger Sayle
-   
-   x86 Foreign Function Interface 
-
-   Permission is hereby granted, free of charge, to any person obtaining
-   a copy of this software and associated documentation files (the
-   ``Software''), to deal in the Software without restriction, including
-   without limitation the rights to use, copy, modify, merge, publish,
-   distribute, sublicense, and/or sell copies of the Software, and to
-   permit persons to whom the Software is furnished to do so, subject to
-   the following conditions:
-
-   The above copyright notice and this permission notice shall be included
-   in all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
-   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-   OTHER DEALINGS IN THE SOFTWARE.
-   ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-#include <stdlib.h>
-
-/* ffi_prep_args is called by the assembly routine once stack space
-   has been allocated for the function's arguments */
-
-extern void Py_FatalError(const char *msg);
-
-/*@-exportheader@*/
-void ffi_prep_args(char *stack, extended_cif *ecif)
-/*@=exportheader@*/
-{
-  register unsigned int i;
-  register void **p_argv;
-  register char *argp;
-  register ffi_type **p_arg;
-
-  argp = stack;
-  if (ecif->cif->flags == FFI_TYPE_STRUCT)
-    {
-      *(void **) argp = ecif->rvalue;
-      argp += sizeof(void *);
-    }
-
-  p_argv = ecif->avalue;
-
-  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
-       i != 0;
-       i--, p_arg++)
-    {
-      size_t z;
-
-      /* Align if necessary */
-      if ((sizeof(void *) - 1) & (size_t) argp)
-	argp = (char *) ALIGN(argp, sizeof(void *));
-
-      z = (*p_arg)->size;
-      if (z < sizeof(int))
-	{
-	  z = sizeof(int);
-	  switch ((*p_arg)->type)
-	    {
-	    case FFI_TYPE_SINT8:
-	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
-	      break;
-
-	    case FFI_TYPE_UINT8:
-	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
-	      break;
-
-	    case FFI_TYPE_SINT16:
-	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
-	      break;
-
-	    case FFI_TYPE_UINT16:
-	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
-	      break;
-
-	    case FFI_TYPE_SINT32:
-	      *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
-	      break;
-
-	    case FFI_TYPE_UINT32:
-	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
-	      break;
-
-	    case FFI_TYPE_STRUCT:
-	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
-	      break;
-
-	    default:
-	      FFI_ASSERT(0);
-	    }
-	}
-#ifdef _WIN64
-      else if (z != 1 && z != 2 && z != 4 && z != 8)
-        {
-          /* On Win64, if a single argument takes more than 8 bytes,
-             then it is always passed by reference. */
-          *(void **)argp = *p_argv;
-          z = 8;
-        }
-#endif
-      else
-	{
-	  memcpy(argp, *p_argv, z);
-	}
-      p_argv++;
-      argp += z;
-    }
-
-  if (argp - stack > (long)ecif->cif->bytes)
-    {
-      Py_FatalError("FFI BUG: not enough stack space for arguments");
-    }
-  return;
-}
-
-/* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
-{
-  /* Set the return type flag */
-  switch (cif->rtype->type)
-    {
-    case FFI_TYPE_VOID:
-    case FFI_TYPE_SINT64:
-    case FFI_TYPE_FLOAT:
-    case FFI_TYPE_DOUBLE:
-    case FFI_TYPE_LONGDOUBLE:
-      cif->flags = (unsigned) cif->rtype->type;
-      break;
-
-    case FFI_TYPE_STRUCT:
-      /* MSVC returns small structures in registers.  Put in cif->flags
-         the value FFI_TYPE_STRUCT only if the structure is big enough;
-         otherwise, put the 4- or 8-bytes integer type. */
-      if (cif->rtype->size == 1 ||
-          cif->rtype->size == 2 ||
-          cif->rtype->size == 4)
-        cif->flags = FFI_TYPE_INT;
-      else if (cif->rtype->size == 8)
-        cif->flags = FFI_TYPE_SINT64;
-      else
-        cif->flags = FFI_TYPE_STRUCT;
-      break;
-
-    case FFI_TYPE_UINT64:
-#ifdef _WIN64
-    case FFI_TYPE_POINTER:
-#endif
-      cif->flags = FFI_TYPE_SINT64;
-      break;
-
-    default:
-      cif->flags = FFI_TYPE_INT;
-      break;
-    }
-
-  return FFI_OK;
-}
-
-#ifdef _WIN32
-extern int
-ffi_call_x86(void (*)(char *, extended_cif *), 
-	     /*@out@*/ extended_cif *, 
-	     unsigned, unsigned, 
-	     /*@out@*/ unsigned *, 
-	     void (*fn)());
-#endif
-
-#ifdef _WIN64
-extern int
-ffi_call_AMD64(void (*)(char *, extended_cif *),
-		 /*@out@*/ extended_cif *,
-		 unsigned, unsigned,
-		 /*@out@*/ unsigned *,
-		 void (*fn)());
-#endif
-
-int
-ffi_call(/*@dependent@*/ ffi_cif *cif, 
-	 void (*fn)(), 
-	 /*@out@*/ void *rvalue, 
-	 /*@dependent@*/ void **avalue)
-{
-  extended_cif ecif;
-
-  ecif.cif = cif;
-  ecif.avalue = avalue;
-  
-  /* If the return value is a struct and we don't have a return	*/
-  /* value address then we need to make one		        */
-
-  if ((rvalue == NULL) && 
-      (cif->flags == FFI_TYPE_STRUCT))
-    {
-      /*@-sysunrecog@*/
-      ecif.rvalue = alloca(cif->rtype->size);
-      /*@=sysunrecog@*/
-    }
-  else
-    ecif.rvalue = rvalue;
-    
-  
-  switch (cif->abi) 
-    {
-#if !defined(_WIN64)
-    case FFI_SYSV:
-    case FFI_STDCALL:
-      return ffi_call_x86(ffi_prep_args, &ecif, cif->bytes, 
-			  cif->flags, ecif.rvalue, fn);
-      break;
-#else
-    case FFI_SYSV:
-      /*@-usedef@*/
-      return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes,
-			   cif->flags, ecif.rvalue, fn);
-      /*@=usedef@*/
-      break;
-#endif
-
-    default:
-      FFI_ASSERT(0);
-      break;
-    }
-  return -1; /* theller: Hrm. */
-}
-
-
-/** private members **/
-
-static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
-					  void** args, ffi_cif* cif);
-/* This function is jumped to by the trampoline */
-
-#ifdef _WIN64
-void *
-#else
-static void __fastcall
-#endif
-ffi_closure_SYSV (ffi_closure *closure, char *argp)
-{
-  // this is our return value storage
-  long double    res;
-
-  // our various things...
-  ffi_cif       *cif;
-  void         **arg_area;
-  unsigned short rtype;
-  void          *resp = (void*)&res;
-  void *args = argp + sizeof(void *);
-
-  cif         = closure->cif;
-  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
-
-  /* this call will initialize ARG_AREA, such that each
-   * element in that array points to the corresponding 
-   * value on the stack; and if the function returns
-   * a structure, it will re-set RESP to point to the
-   * structure return address.  */
-
-  ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
-  
-  (closure->fun) (cif, resp, arg_area, closure->user_data);
-
-  rtype = cif->flags;
-
-#if defined(_WIN32) && !defined(_WIN64)
-#ifdef _MSC_VER
-  /* now, do a generic return based on the value of rtype */
-  if (rtype == FFI_TYPE_INT)
-    {
-	    _asm mov eax, resp ;
-	    _asm mov eax, [eax] ;
-    }
-  else if (rtype == FFI_TYPE_FLOAT)
-    {
-	    _asm mov eax, resp ;
-	    _asm fld DWORD PTR [eax] ;
-//      asm ("flds (%0)" : : "r" (resp) : "st" );
-    }
-  else if (rtype == FFI_TYPE_DOUBLE || rtype == FFI_TYPE_LONGDOUBLE)
-    {
-	    _asm mov eax, resp ;
-	    _asm fld QWORD PTR [eax] ;
-//      asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
-    }
-  else if (rtype == FFI_TYPE_SINT64)
-    {
-	    _asm mov edx, resp ;
-	    _asm mov eax, [edx] ;
-	    _asm mov edx, [edx + 4] ;
-//      asm ("movl 0(%0),%%eax;"
-//	   "movl 4(%0),%%edx" 
-//	   : : "r"(resp)
-//	   : "eax", "edx");
-    }
-  else if (rtype == FFI_TYPE_STRUCT)
-    {
-	    _asm mov eax, resp ;
-    }
-#else
-  /* now, do a generic return based on the value of rtype */
-  if (rtype == FFI_TYPE_INT)
-    {
-      asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
-    }
-  else if (rtype == FFI_TYPE_FLOAT)
-    {
-      asm ("flds (%0)" : : "r" (resp) : "st" );
-    }
-  else if (rtype == FFI_TYPE_DOUBLE || rtype == FFI_TYPE_LONGDOUBLE)
-    {
-      asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
-    }
-  else if (rtype == FFI_TYPE_SINT64)
-    {
-      asm ("movl 0(%0),%%eax;"
-	   "movl 4(%0),%%edx" 
-	   : : "r"(resp)
-	   : "eax", "edx");
-    }
-  else if (rtype == FFI_TYPE_STRUCT)
-    {
-      asm ("movl %0,%%eax" : : "r" (resp) : "eax");
-    }
-#endif
-#endif
-
-#ifdef _WIN64
-  /* The result is returned in rax.  This does the right thing for
-     result types except for floats; we have to 'mov xmm0, rax' in the
-     caller to correct this.
-  */
-  if (rtype == FFI_TYPE_STRUCT)
-      return resp;
-  return *(void **)resp;
-#endif
-}
-
-/*@-exportheader@*/
-static void 
-ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
-			    void **avalue, ffi_cif *cif)
-/*@=exportheader@*/
-{
-  register unsigned int i;
-  register void **p_argv;
-  register char *argp;
-  register ffi_type **p_arg;
-
-  argp = stack;
-
-  if ( cif->flags == FFI_TYPE_STRUCT ) {
-    *rvalue = *(void **) argp;
-    argp += 4;
-  }
-
-  p_argv = avalue;
-
-  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
-    {
-      size_t z;
-
-      /* Align if necessary */
-      if ((sizeof(char *) - 1) & (size_t) argp) {
-	argp = (char *) ALIGN(argp, sizeof(char*));
-      }
-
-      z = (*p_arg)->size;
-
-      /* because we're little endian, this is what it turns into.   */
-
-#ifdef _WIN64
-      if (z != 1 && z != 2 && z != 4 && z != 8)
-        {
-          /* On Win64, if a single argument takes more than 8 bytes,
-             then it is always passed by reference. */
-          *p_argv = *((void**) argp);
-          z = 8;
-        }
-      else
-#endif
-      *p_argv = (void*) argp;
-
-      p_argv++;
-      argp += z;
-    }
-  
-  return;
-}
-
-/* the cif must already be prep'ed */
-extern void ffi_closure_OUTER();
-
-ffi_status
-ffi_prep_closure_loc (ffi_closure* closure,
-					  ffi_cif* cif,
-					  void (*fun)(ffi_cif*,void*,void**,void*),
-					  void *user_data,
-					  void *codeloc)
-{
-  short bytes;
-  char *tramp;
-#ifdef _WIN64
-  int mask = 0;
-#endif
-  FFI_ASSERT (cif->abi == FFI_SYSV);
-  
-  if (cif->abi == FFI_SYSV)
-    bytes = 0;
-#if !defined(_WIN64)
-  else if (cif->abi == FFI_STDCALL)
-    bytes = cif->bytes;
-#endif
-  else
-    return FFI_BAD_ABI;
-
-  tramp = &closure->tramp[0];
-
-#define BYTES(text) memcpy(tramp, text, sizeof(text)), tramp += sizeof(text)-1
-#define POINTER(x) *(void**)tramp = (void*)(x), tramp += sizeof(void*)
-#define SHORT(x) *(short*)tramp = x, tramp += sizeof(short)
-#define INT(x) *(int*)tramp = x, tramp += sizeof(int)
-
-#ifdef _WIN64
-  if (cif->nargs >= 1 &&
-      (cif->arg_types[0]->type == FFI_TYPE_FLOAT
-       || cif->arg_types[0]->type == FFI_TYPE_DOUBLE))
-    mask |= 1;
-  if (cif->nargs >= 2 &&
-      (cif->arg_types[1]->type == FFI_TYPE_FLOAT
-       || cif->arg_types[1]->type == FFI_TYPE_DOUBLE))
-    mask |= 2;
-  if (cif->nargs >= 3 &&
-      (cif->arg_types[2]->type == FFI_TYPE_FLOAT
-       || cif->arg_types[2]->type == FFI_TYPE_DOUBLE))
-    mask |= 4;
-  if (cif->nargs >= 4 &&
-      (cif->arg_types[3]->type == FFI_TYPE_FLOAT
-       || cif->arg_types[3]->type == FFI_TYPE_DOUBLE))
-    mask |= 8;
-
-  /* if we return a non-small struct, then the first argument is a pointer
-   * to the return area, and all real arguments are shifted by one */
-  if (cif->flags == FFI_TYPE_STRUCT)
-    mask = (mask & ~8) << 1;
-
-  /* 41 BB ----         mov         r11d,mask */
-  BYTES("\x41\xBB"); INT(mask);
-
-  /* 48 B8 --------     mov         rax, closure			*/
-  BYTES("\x48\xB8"); POINTER(closure);
-
-  /* 49 BA --------     mov         r10, ffi_closure_OUTER */
-  BYTES("\x49\xBA"); POINTER(ffi_closure_OUTER);
-
-  /* 41 FF E2           jmp         r10 */
-  BYTES("\x41\xFF\xE2");
-
-#else
-
-  /* mov ecx, closure */
-  BYTES("\xb9"); POINTER(closure);
-
-  /* mov edx, esp */
-  BYTES("\x8b\xd4");
-
-  /* call ffi_closure_SYSV */
-  BYTES("\xe8"); POINTER((char*)&ffi_closure_SYSV - (tramp + 4));
-
-  /* ret bytes */
-  BYTES("\xc2");
-  SHORT(bytes);
-  
-#endif
-
-  if (tramp - &closure->tramp[0] > FFI_TRAMPOLINE_SIZE)
-    Py_FatalError("FFI_TRAMPOLINE_SIZE too small in " __FILE__);
-
-  closure->cif  = cif;
-  closure->user_data = user_data;
-  closure->fun  = fun;
-  return FFI_OK;
-}
diff --git a/c/libffi_x86_x64/ffi.h b/c/libffi_x86_x64/ffi.h
deleted file mode 100644
index 97cdb59..0000000
--- a/c/libffi_x86_x64/ffi.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/* -----------------------------------------------------------------*-C-*-
-   libffi 2.00-beta - Copyright (c) 1996-2003  Red Hat, Inc.
-
-   Permission is hereby granted, free of charge, to any person obtaining
-   a copy of this software and associated documentation files (the
-   ``Software''), to deal in the Software without restriction, including
-   without limitation the rights to use, copy, modify, merge, publish,
-   distribute, sublicense, and/or sell copies of the Software, and to
-   permit persons to whom the Software is furnished to do so, subject to
-   the following conditions:
-
-   The above copyright notice and this permission notice shall be included
-   in all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
-   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-   OTHER DEALINGS IN THE SOFTWARE.
-
-   ----------------------------------------------------------------------- */
-
-/* -------------------------------------------------------------------
-   The basic API is described in the README file.
-
-   The raw API is designed to bypass some of the argument packing
-   and unpacking on architectures for which it can be avoided.
-
-   The closure API allows interpreted functions to be packaged up
-   inside a C function pointer, so that they can be called as C functions,
-   with no understanding on the client side that they are interpreted.
-   It can also be used in other cases in which it is necessary to package
-   up a user specified parameter and a function pointer as a single
-   function pointer.
-
-   The closure API must be implemented in order to get its functionality,
-   e.g. for use by gij.  Routines are provided to emulate the raw API
-   if the underlying platform doesn't allow faster implementation.
-
-   More details on the raw and cloure API can be found in:
-
-   http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
-
-   and
-
-   http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
-   -------------------------------------------------------------------- */
-
-#ifndef LIBFFI_H
-#define LIBFFI_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Specify which architecture libffi is configured for. */
-//XXX #define X86
-
-/* ---- System configuration information --------------------------------- */
-
-#include <ffitarget.h>
-
-#ifndef LIBFFI_ASM
-
-#include <stddef.h>
-#include <limits.h>
-
-/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
-   But we can find it either under the correct ANSI name, or under GNU
-   C's internal name.  */
-#ifdef LONG_LONG_MAX
-# define FFI_LONG_LONG_MAX LONG_LONG_MAX
-#else
-# ifdef LLONG_MAX
-#  define FFI_LONG_LONG_MAX LLONG_MAX
-# else
-#  ifdef __GNUC__
-#   define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
-#  endif
-#  ifdef _MSC_VER
-#   define FFI_LONG_LONG_MAX _I64_MAX
-#  endif
-# endif
-#endif
-
-#if SCHAR_MAX == 127
-# define ffi_type_uchar                ffi_type_uint8
-# define ffi_type_schar                ffi_type_sint8
-#else
- #error "char size not supported"
-#endif
-
-#if SHRT_MAX == 32767
-# define ffi_type_ushort       ffi_type_uint16
-# define ffi_type_sshort       ffi_type_sint16
-#elif SHRT_MAX == 2147483647
-# define ffi_type_ushort       ffi_type_uint32
-# define ffi_type_sshort       ffi_type_sint32
-#else
- #error "short size not supported"
-#endif
-
-#if INT_MAX == 32767
-# define ffi_type_uint         ffi_type_uint16
-# define ffi_type_sint         ffi_type_sint16
-#elif INT_MAX == 2147483647
-# define ffi_type_uint         ffi_type_uint32
-# define ffi_type_sint         ffi_type_sint32
-#elif INT_MAX == 9223372036854775807
-# define ffi_type_uint         ffi_type_uint64
-# define ffi_type_sint         ffi_type_sint64
-#else
- #error "int size not supported"
-#endif
-
-#define ffi_type_ulong         ffi_type_uint64
-#define ffi_type_slong         ffi_type_sint64
-#if LONG_MAX == 2147483647
-# if FFI_LONG_LONG_MAX != 9223372036854775807
-  #error "no 64-bit data type supported"
-# endif
-#elif LONG_MAX != 9223372036854775807
- #error "long size not supported"
-#endif
-
-/* The closure code assumes that this works on pointers, i.e. a size_t	*/
-/* can hold a pointer.							*/
-
-typedef struct _ffi_type
-{
-  size_t size;
-  unsigned short alignment;
-  unsigned short type;
-  /*@null@*/ struct _ffi_type **elements;
-} ffi_type;
-
-/* These are defined in types.c */
-extern ffi_type ffi_type_void;
-extern ffi_type ffi_type_uint8;
-extern ffi_type ffi_type_sint8;
-extern ffi_type ffi_type_uint16;
-extern ffi_type ffi_type_sint16;
-extern ffi_type ffi_type_uint32;
-extern ffi_type ffi_type_sint32;
-extern ffi_type ffi_type_uint64;
-extern ffi_type ffi_type_sint64;
-extern ffi_type ffi_type_float;
-extern ffi_type ffi_type_double;
-extern ffi_type ffi_type_longdouble;
-extern ffi_type ffi_type_pointer;
-
-
-typedef enum {
-  FFI_OK = 0,
-  FFI_BAD_TYPEDEF,
-  FFI_BAD_ABI 
-} ffi_status;
-
-typedef unsigned FFI_TYPE;
-
-typedef struct {
-  ffi_abi abi;
-  unsigned nargs;
-  /*@dependent@*/ ffi_type **arg_types;
-  /*@dependent@*/ ffi_type *rtype;
-  unsigned bytes;
-  unsigned flags;
-#ifdef FFI_EXTRA_CIF_FIELDS
-  FFI_EXTRA_CIF_FIELDS;
-#endif
-} ffi_cif;
-
-/* ---- Definitions for the raw API -------------------------------------- */
-
-#ifdef _WIN64
-#define FFI_SIZEOF_ARG 8
-#else
-#define FFI_SIZEOF_ARG 4
-#endif
-
-typedef union {
-  ffi_sarg  sint;
-  ffi_arg   uint;
-  float	    flt;
-  char      data[FFI_SIZEOF_ARG];
-  void*     ptr;
-} ffi_raw;
-
-void ffi_raw_call (/*@dependent@*/ ffi_cif *cif, 
-		   void (*fn)(), 
-		   /*@out@*/ void *rvalue, 
-		   /*@dependent@*/ ffi_raw *avalue);
-
-void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
-void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
-size_t ffi_raw_size (ffi_cif *cif);
-
-/* This is analogous to the raw API, except it uses Java parameter	*/
-/* packing, even on 64-bit machines.  I.e. on 64-bit machines		*/
-/* longs and doubles are followed by an empty 64-bit word.		*/
-
-void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif, 
-		        void (*fn)(), 
-		        /*@out@*/ void *rvalue, 
-		        /*@dependent@*/ ffi_raw *avalue);
-
-void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
-void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
-size_t ffi_java_raw_size (ffi_cif *cif);
-
-/* ---- Definitions for closures ----------------------------------------- */
-
-#if FFI_CLOSURES
-
-typedef struct {
-  char tramp[FFI_TRAMPOLINE_SIZE];
-  ffi_cif   *cif;
-  void     (*fun)(ffi_cif*,void*,void**,void*);
-  void      *user_data;
-} ffi_closure;
-
-void ffi_closure_free(void *);
-void *ffi_closure_alloc (size_t size, void **code);
-
-ffi_status
-ffi_prep_closure_loc (ffi_closure*,
-		  ffi_cif *,
-		  void (*fun)(ffi_cif*,void*,void**,void*),
-		  void *user_data,
-		  void *codeloc);
-
-/* AR: for cffi we need the following API, and not the _loc version */
-#define ffi_prep_closure(a,b,c,d)  ffi_prep_closure_loc(a,b,c,d,a)
-
-typedef struct {
-  char tramp[FFI_TRAMPOLINE_SIZE];
-
-  ffi_cif   *cif;
-
-#if !FFI_NATIVE_RAW_API
-
-  /* if this is enabled, then a raw closure has the same layout 
-     as a regular closure.  We use this to install an intermediate 
-     handler to do the transaltion, void** -> ffi_raw*. */
-
-  void     (*translate_args)(ffi_cif*,void*,void**,void*);
-  void      *this_closure;
-
-#endif
-
-  void     (*fun)(ffi_cif*,void*,ffi_raw*,void*);
-  void      *user_data;
-
-} ffi_raw_closure;
-
-ffi_status
-ffi_prep_raw_closure (ffi_raw_closure*,
-		      ffi_cif *cif,
-		      void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-		      void *user_data);
-
-ffi_status
-ffi_prep_java_raw_closure (ffi_raw_closure*,
-		           ffi_cif *cif,
-		           void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-		           void *user_data);
-
-#endif /* FFI_CLOSURES */
-
-/* ---- Public interface definition -------------------------------------- */
-
-ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, 
-			ffi_abi abi,
-			unsigned int nargs, 
-			/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, 
-			/*@dependent@*/ ffi_type **atypes);
-
-int
-ffi_call(/*@dependent@*/ ffi_cif *cif, 
-	 void (*fn)(), 
-	 /*@out@*/ void *rvalue, 
-	 /*@dependent@*/ void **avalue);
-
-/* Useful for eliminating compiler warnings */
-#define FFI_FN(f) ((void (*)())f)
-
-/* ---- Definitions shared with assembly code ---------------------------- */
-
-#endif
-
-/* If these change, update src/mips/ffitarget.h. */
-#define FFI_TYPE_VOID       0    
-#define FFI_TYPE_INT        1
-#define FFI_TYPE_FLOAT      2    
-#define FFI_TYPE_DOUBLE     3
-#if 1
-#define FFI_TYPE_LONGDOUBLE 4
-#else
-#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
-#endif
-#define FFI_TYPE_UINT8      5   
-#define FFI_TYPE_SINT8      6
-#define FFI_TYPE_UINT16     7 
-#define FFI_TYPE_SINT16     8
-#define FFI_TYPE_UINT32     9
-#define FFI_TYPE_SINT32     10
-#define FFI_TYPE_UINT64     11
-#define FFI_TYPE_SINT64     12
-#define FFI_TYPE_STRUCT     13
-#define FFI_TYPE_POINTER    14
-
-/* This should always refer to the last type code (for sanity checks) */
-#define FFI_TYPE_LAST       FFI_TYPE_POINTER
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/c/libffi_x86_x64/ffi_common.h b/c/libffi_x86_x64/ffi_common.h
deleted file mode 100644
index 43fb83b..0000000
--- a/c/libffi_x86_x64/ffi_common.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -----------------------------------------------------------------------
-   ffi_common.h - Copyright (c) 1996  Red Hat, Inc.
-
-   Common internal definitions and macros. Only necessary for building
-   libffi.
-   ----------------------------------------------------------------------- */
-
-#ifndef FFI_COMMON_H
-#define FFI_COMMON_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <fficonfig.h>
-#include <malloc.h>
-
-/* Check for the existence of memcpy. */
-#if STDC_HEADERS
-# include <string.h>
-#else
-# ifndef HAVE_MEMCPY
-#  define memcpy(d, s, n) bcopy ((s), (d), (n))
-# endif
-#endif
-
-#if defined(FFI_DEBUG) 
-#include <stdio.h>
-#endif
-
-#ifdef FFI_DEBUG
-/*@exits@*/ void ffi_assert(/*@temp@*/ char *expr, /*@temp@*/ char *file, int line);
-void ffi_stop_here(void);
-void ffi_type_test(/*@temp@*/ /*@out@*/ ffi_type *a, /*@temp@*/ char *file, int line);
-
-#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
-#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
-#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
-#else
-#define FFI_ASSERT(x) 
-#define FFI_ASSERT_AT(x, f, l)
-#define FFI_ASSERT_VALID_TYPE(x)
-#endif
-
-#define ALIGN(v, a)  (((((size_t) (v))-1) | ((a)-1))+1)
-
-/* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
-
-/* Extended cif, used in callback from assembly routine */
-typedef struct
-{
-  /*@dependent@*/ ffi_cif *cif;
-  /*@dependent@*/ void *rvalue;
-  /*@dependent@*/ void **avalue;
-} extended_cif;
-
-/* Terse sized type definitions.  */
-typedef unsigned int UINT8  __attribute__((__mode__(__QI__)));
-typedef signed int   SINT8  __attribute__((__mode__(__QI__)));
-typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
-typedef signed int   SINT16 __attribute__((__mode__(__HI__)));
-typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
-typedef signed int   SINT32 __attribute__((__mode__(__SI__)));
-typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
-typedef signed int   SINT64 __attribute__((__mode__(__DI__)));
-
-typedef float FLOAT32;
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
diff --git a/c/libffi_x86_x64/fficonfig.h b/c/libffi_x86_x64/fficonfig.h
deleted file mode 100644
index c14f653..0000000
--- a/c/libffi_x86_x64/fficonfig.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* fficonfig.h.  Originally created by configure, now hand_maintained for MSVC. */
-
-/* fficonfig.h.  Generated automatically by configure.  */
-/* fficonfig.h.in.  Generated automatically from configure.in by autoheader.  */
-
-/* Define this for MSVC, but not for mingw32! */
-#ifdef _MSC_VER
-#define __attribute__(x) /* */
-#endif
-#define alloca _alloca
-
-/*----------------------------------------------------------------*/
-
-/* Define if using alloca.c.  */
-/* #undef C_ALLOCA */
-
-/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
-   This function is required for alloca.c support on those systems.  */
-/* #undef CRAY_STACKSEG_END */
-
-/* Define if you have alloca, as a function or macro.  */
-#define HAVE_ALLOCA 1
-
-/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
-/* #define HAVE_ALLOCA_H 1 */
-
-/* If using the C implementation of alloca, define if you know the
-   direction of stack growth for your system; otherwise it will be
-   automatically deduced at run-time.
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown
- */
-/* #undef STACK_DIRECTION */
-
-/* Define if you have the ANSI C header files.  */
-#define STDC_HEADERS 1
-
-/* Define if you have the memcpy function.  */
-#define HAVE_MEMCPY 1
-
-/* Define if read-only mmap of a plain file works. */
-//#define HAVE_MMAP_FILE 1
-
-/* Define if mmap of /dev/zero works. */
-//#define HAVE_MMAP_DEV_ZERO 1
-
-/* Define if mmap with MAP_ANON(YMOUS) works. */
-//#define HAVE_MMAP_ANON 1
-
-/* The number of bytes in type double */
-#define SIZEOF_DOUBLE 8
-
-/* The number of bytes in type long double */
-#define SIZEOF_LONG_DOUBLE 12
-
-/* Define if you have the long double type and it is bigger than a double */
-#define HAVE_LONG_DOUBLE 1
-
-/* whether byteorder is bigendian */
-/* #undef WORDS_BIGENDIAN */
-
-/* Define if the host machine stores words of multi-word integers in
-   big-endian order. */
-/* #undef HOST_WORDS_BIG_ENDIAN */
-
-/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */
-#define BYTEORDER 1234
-
-/* Define if your assembler and linker support unaligned PC relative relocs. */
-/* #undef HAVE_AS_SPARC_UA_PCREL */
-
-/* Define if your assembler supports .register. */
-/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
-
-/* Define if .eh_frame sections should be read-only. */
-/* #undef HAVE_RO_EH_FRAME */
-
-/* Define to the flags needed for the .section .eh_frame directive. */
-/* #define EH_FRAME_FLAGS "aw" */
-
-/* Define to the flags needed for the .section .eh_frame directive. */
-/* #define EH_FRAME_FLAGS "aw" */
-
-/* Define this if you want extra debugging. */
-/* #undef FFI_DEBUG */
-
-/* Define this is you do not want support for aggregate types. */
-/* #undef FFI_NO_STRUCTS */
-
-/* Define this is you do not want support for the raw API. */
-/* #undef FFI_NO_RAW_API */
-
-/* Define this if you are using Purify and want to suppress spurious messages. */
-/* #undef USING_PURIFY */
-
diff --git a/c/libffi_x86_x64/ffitarget.h b/c/libffi_x86_x64/ffitarget.h
deleted file mode 100644
index 85f5ee8..0000000
--- a/c/libffi_x86_x64/ffitarget.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -----------------------------------------------------------------*-C-*-
-   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
-   Target configuration macros for x86 and x86-64.
-
-   Permission is hereby granted, free of charge, to any person obtaining
-   a copy of this software and associated documentation files (the
-   ``Software''), to deal in the Software without restriction, including
-   without limitation the rights to use, copy, modify, merge, publish,
-   distribute, sublicense, and/or sell copies of the Software, and to
-   permit persons to whom the Software is furnished to do so, subject to
-   the following conditions:
-
-   The above copyright notice and this permission notice shall be included
-   in all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
-   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-   OTHER DEALINGS IN THE SOFTWARE.
-
-   ----------------------------------------------------------------------- */
-
-#ifndef LIBFFI_TARGET_H
-#define LIBFFI_TARGET_H
-
-/* ---- System specific configurations ----------------------------------- */
-
-#if defined (X86_64) && defined (__i386__)
-#undef X86_64
-#define X86
-#endif
-
-/* ---- Generic type definitions ----------------------------------------- */
-
-#ifndef LIBFFI_ASM
-#ifndef _WIN64
-typedef unsigned long          ffi_arg;
-#else
-typedef unsigned __int64       ffi_arg;
-#endif
-typedef signed long            ffi_sarg;
-
-typedef enum ffi_abi {
-  FFI_FIRST_ABI = 0,
-
-  /* ---- Intel x86 Win32 ---------- */
-  FFI_SYSV,
-#ifndef _WIN64
-  FFI_STDCALL,
-#endif
-  /* TODO: Add fastcall support for the sake of completeness */
-  FFI_DEFAULT_ABI = FFI_SYSV,
-
-  /* ---- Intel x86 and AMD x86-64 - */
-/* #if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) */
-/*   FFI_SYSV, */
-/*   FFI_UNIX64,*/   /* Unix variants all use the same ABI for x86-64  */
-/* #ifdef __i386__ */
-/*   FFI_DEFAULT_ABI = FFI_SYSV, */
-/* #else */
-/*   FFI_DEFAULT_ABI = FFI_UNIX64, */
-/* #endif */
-/* #endif */
-
-  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
-} ffi_abi;
-#endif
-
-/* ---- Definitions for closures ----------------------------------------- */
-
-#define FFI_CLOSURES 1
-
-#ifdef _WIN64
-#define FFI_TRAMPOLINE_SIZE 29
-#define FFI_NATIVE_RAW_API 0
-#else
-#define FFI_TRAMPOLINE_SIZE 15
-#define FFI_NATIVE_RAW_API 1	/* x86 has native raw api support */
-#endif
-
-#endif
-
diff --git a/c/libffi_x86_x64/prep_cif.c b/c/libffi_x86_x64/prep_cif.c
deleted file mode 100644
index df94a98..0000000
--- a/c/libffi_x86_x64/prep_cif.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* -----------------------------------------------------------------------
-   prep_cif.c - Copyright (c) 1996, 1998  Red Hat, Inc.
-
-   Permission is hereby granted, free of charge, to any person obtaining
-   a copy of this software and associated documentation files (the
-   ``Software''), to deal in the Software without restriction, including
-   without limitation the rights to use, copy, modify, merge, publish,
-   distribute, sublicense, and/or sell copies of the Software, and to
-   permit persons to whom the Software is furnished to do so, subject to
-   the following conditions:
-
-   The above copyright notice and this permission notice shall be included
-   in all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
-   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-   OTHER DEALINGS IN THE SOFTWARE.
-   ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-#include <stdlib.h>
-
-
-/* Round up to FFI_SIZEOF_ARG. */
-
-#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
-
-/* Perform machine independent initialization of aggregate type
-   specifications. */
-
-static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
-{
-  ffi_type **ptr; 
-
-  FFI_ASSERT(arg != NULL);
-
-  /*@-usedef@*/
-
-  FFI_ASSERT(arg->elements != NULL);
-  FFI_ASSERT(arg->size == 0);
-  FFI_ASSERT(arg->alignment == 0);
-
-  ptr = &(arg->elements[0]);
-
-  while ((*ptr) != NULL)
-    {
-      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
-	return FFI_BAD_TYPEDEF;
-      
-      /* Perform a sanity check on the argument type */
-      FFI_ASSERT_VALID_TYPE(*ptr);
-
-      arg->size = ALIGN(arg->size, (*ptr)->alignment);
-      arg->size += (*ptr)->size;
-
-      arg->alignment = (arg->alignment > (*ptr)->alignment) ? 
-	arg->alignment : (*ptr)->alignment;
-
-      ptr++;
-    }
-
-  /* Structure size includes tail padding.  This is important for
-     structures that fit in one register on ABIs like the PowerPC64
-     Linux ABI that right justify small structs in a register.
-     It's also needed for nested structure layout, for example
-     struct A { long a; char b; }; struct B { struct A x; char y; };
-     should find y at an offset of 2*sizeof(long) and result in a
-     total size of 3*sizeof(long).  */
-  arg->size = ALIGN (arg->size, arg->alignment);
-
-  if (arg->size == 0)
-    return FFI_BAD_TYPEDEF;
-  else
-    return FFI_OK;
-
-  /*@=usedef@*/
-}
-
-/* Perform machine independent ffi_cif preparation, then call
-   machine dependent routine. */
-
-ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, 
-			ffi_abi abi, unsigned int nargs, 
-			/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, 
-			/*@dependent@*/ ffi_type **atypes)
-{
-  unsigned bytes = 0;
-  unsigned int i;
-  ffi_type **ptr;
-
-  FFI_ASSERT(cif != NULL);
-  FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
-
-  cif->abi = abi;
-  cif->arg_types = atypes;
-  cif->nargs = nargs;
-  cif->rtype = rtype;
-
-  cif->flags = 0;
-
-  /* Initialize the return type if necessary */
-  /*@-usedef@*/
-  if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
-    return FFI_BAD_TYPEDEF;
-  /*@=usedef@*/
-
-  /* Perform a sanity check on the return type */
-  FFI_ASSERT_VALID_TYPE(cif->rtype);
-
-  /* x86-64 and s390 stack space allocation is handled in prep_machdep.  */
-#if !defined M68K && !defined __x86_64__ && !defined S390
-  /* Make space for the return structure pointer */
-  if (cif->rtype->type == FFI_TYPE_STRUCT
-#ifdef _WIN32
-      && (cif->rtype->size != 1)  /* MSVC returns small structs in registers */
-      && (cif->rtype->size != 2)
-      && (cif->rtype->size != 4)
-      && (cif->rtype->size != 8)
-#endif
-#ifdef SPARC
-      && (cif->abi != FFI_V9 || cif->rtype->size > 32)
-#endif
-      )
-    bytes = STACK_ARG_SIZE(sizeof(void*));
-#endif
-
-  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
-    {
-
-      /* Initialize any uninitialized aggregate type definitions */
-      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
-	return FFI_BAD_TYPEDEF;
-
-      /* Perform a sanity check on the argument type, do this 
-	 check after the initialization.  */
-      FFI_ASSERT_VALID_TYPE(*ptr);
-
-#if !defined __x86_64__ && !defined S390
-#ifdef SPARC
-      if (((*ptr)->type == FFI_TYPE_STRUCT
-	   && ((*ptr)->size > 16 || cif->abi != FFI_V9))
-	  || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
-	      && cif->abi != FFI_V9))
-	bytes += sizeof(void*);
-      else
-#endif
-	{
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
-		/* Don't know if this is a libffi bug or not.  At least on
-		   Windows with MSVC, function call parameters are *not*
-		   aligned in the same way as structure fields are, they are
-		   only aligned in integer boundaries.
-
-		   This doesn't do any harm for cdecl functions and closures,
-		   since the caller cleans up the stack, but it is wrong for
-		   stdcall functions where the callee cleans.
-		*/
-
-	  /* Add any padding if necessary */
-	  if (((*ptr)->alignment - 1) & bytes)
-	    bytes = ALIGN(bytes, (*ptr)->alignment);
-	  
-#endif
-	  bytes += STACK_ARG_SIZE((*ptr)->size);
-	}
-#endif
-    }
-
-#ifdef _WIN64
-  /* Function call needs at least 40 bytes stack size, on win64 AMD64 */
-  if (bytes < 40)
-      bytes = 40;
-#endif
-
-  cif->bytes = bytes;
-
-  /* Perform machine dependent cif processing */
-  return ffi_prep_cif_machdep(cif);
-}
diff --git a/c/libffi_x86_x64/types.c b/c/libffi_x86_x64/types.c
deleted file mode 100644
index 4433ac2..0000000
--- a/c/libffi_x86_x64/types.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* -----------------------------------------------------------------------
-   types.c - Copyright (c) 1996, 1998  Red Hat, Inc.
-   
-   Predefined ffi_types needed by libffi.
-
-   Permission is hereby granted, free of charge, to any person obtaining
-   a copy of this software and associated documentation files (the
-   ``Software''), to deal in the Software without restriction, including
-   without limitation the rights to use, copy, modify, merge, publish,
-   distribute, sublicense, and/or sell copies of the Software, and to
-   permit persons to whom the Software is furnished to do so, subject to
-   the following conditions:
-
-   The above copyright notice and this permission notice shall be included
-   in all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
-   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-   OTHER DEALINGS IN THE SOFTWARE.
-   ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-/* Type definitions */
-
-#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) ffi_type ffi_type_##n = { s, a, t, NULL }
-#define FFI_AGGREGATE_TYPEDEF(n, e) ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e }
-
-/* Size and alignment are fake here. They must not be 0. */
-FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID);
-
-FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8);
-FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8);
-FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
-FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
-FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
-FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
-FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
-
-#if defined ALPHA || defined SPARC64 || defined X86_64 || defined S390X \
-    || defined IA64 || defined _WIN64
-
-FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
-
-#else
-
-FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
-
-#endif
-
-#if defined X86 || defined X86_WIN32 || defined ARM || defined M68K
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
-
-#elif defined SH
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
-
-#else
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
-
-#endif
-
-
-#if defined X86 || defined X86_WIN32 || defined M68K
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
-
-#elif defined ARM || defined SH || defined POWERPC_AIX || defined POWERPC_DARWIN
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
-
-#elif defined SPARC
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
-#ifdef SPARC64
-FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
-#else
-FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
-#endif
-
-#elif defined X86_64
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
-
-#else
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
-
-#endif
-
diff --git a/c/libffi_x86_x64/win32.c b/c/libffi_x86_x64/win32.c
deleted file mode 100644
index d1149a8..0000000
--- a/c/libffi_x86_x64/win32.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/* -----------------------------------------------------------------------
-   win32.S - Copyright (c) 1996, 1998, 2001, 2002  Red Hat, Inc.
-	     Copyright (c) 2001  John Beniton
-	     Copyright (c) 2002  Ranjit Mathew
-			
- 
-   X86 Foreign Function Interface
- 
-   Permission is hereby granted, free of charge, to any person obtaining
-   a copy of this software and associated documentation files (the
-   ``Software''), to deal in the Software without restriction, including
-   without limitation the rights to use, copy, modify, merge, publish,
-   distribute, sublicense, and/or sell copies of the Software, and to
-   permit persons to whom the Software is furnished to do so, subject to
-   the following conditions:
- 
-   The above copyright notice and this permission notice shall be included
-   in all copies or substantial portions of the Software.
- 
-   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
-   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-   OTHER DEALINGS IN THE SOFTWARE.
-   ----------------------------------------------------------------------- */
-
-/* theller: almost verbatim translation from gas syntax to MSVC inline
-   assembler code. */
-
-/* theller: ffi_call_x86 now returns an integer - the difference of the stack
-   pointer before and after the function call.  If everything is ok, zero is
-   returned.  If stdcall functions are passed the wrong number of arguments,
-   the difference will be nonzero. */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-__declspec(naked) int
-ffi_call_x86(void (* prepfunc)(char *, extended_cif *), /* 8 */
-	     extended_cif *ecif, /* 12 */
-	     unsigned bytes, /* 16 */
-	     unsigned flags, /* 20 */
-	     unsigned *rvalue, /* 24 */
-	     void (*fn)()) /* 28 */
-{
-	_asm {
-		push ebp
-		mov ebp, esp
-
-		push esi // NEW: this register must be preserved across function calls
-// XXX SAVE ESP NOW!
-		mov esi, esp		// save stack pointer before the call
-
-// Make room for all of the new args.
-		mov ecx, [ebp+16]
-		sub esp, ecx		// sub esp, bytes
-		
-		mov eax, esp
-
-// Place all of the ffi_prep_args in position
-		push [ebp + 12] // ecif
-		push eax
-		call [ebp + 8] // prepfunc
-
-// Return stack to previous state and call the function
-		add esp, 8
-// FIXME: Align the stack to a 128-bit boundary to avoid
-// potential performance hits.
-		call [ebp + 28]
-
-// Load ecif->cif->abi
-		mov ecx, [ebp + 12]
-		mov ecx, [ecx]ecif.cif
-		mov ecx, [ecx]ecif.cif.abi
-		
-		cmp ecx, FFI_STDCALL
-		je noclean
-// STDCALL: Remove the space we pushed for the args
-		mov ecx, [ebp + 16]
-		add esp, ecx
-// CDECL: Caller has already cleaned the stack
-noclean:
-// Check that esp has the same value as before!
-		sub esi, esp
-
-// Load %ecx with the return type code
-		mov ecx, [ebp + 20]
-
-// If the return value pointer is NULL, assume no return value.
-/*
-  Intel asm is weird. We have to explicitely specify 'DWORD PTR' in the nexr instruction,
-  otherwise only one BYTE will be compared (instead of a DWORD)!
- */
-		cmp DWORD PTR [ebp + 24], 0
-		jne sc_retint
-
-// Even if there is no space for the return value, we are
-// obliged to handle floating-point values.
-		cmp ecx, FFI_TYPE_FLOAT
-		jne sc_noretval
-//        fstp  %st(0)
-		fstp st(0)
-
-		jmp sc_epilogue
-
-sc_retint:
-		cmp ecx, FFI_TYPE_INT
-		jne sc_retfloat
-//        # Load %ecx with the pointer to storage for the return value
-		mov ecx, [ebp + 24]
-		mov [ecx + 0], eax
-		jmp sc_epilogue
-
-sc_retfloat:
-		cmp ecx, FFI_TYPE_FLOAT
-		jne sc_retdouble
-// Load %ecx with the pointer to storage for the return value
-		mov ecx, [ebp+24]
-//        fstps (%ecx)
-		fstp DWORD PTR [ecx]
-		jmp sc_epilogue
-
-sc_retdouble:
-		cmp ecx, FFI_TYPE_DOUBLE
-		jne sc_retlongdouble
-//        movl  24(%ebp),%ecx
-		mov ecx, [ebp+24]
-		fstp QWORD PTR [ecx]
-		jmp sc_epilogue
-
-		jmp sc_retlongdouble // avoid warning about unused label
-sc_retlongdouble:
-		cmp ecx, FFI_TYPE_LONGDOUBLE
-		jne sc_retint64
-// Load %ecx with the pointer to storage for the return value
-		mov ecx, [ebp+24]
-//        fstpt (%ecx)
-		fstp QWORD PTR [ecx] /* XXX ??? */
-		jmp sc_epilogue
-
-sc_retint64:
-		cmp ecx, FFI_TYPE_SINT64
-		jne sc_retstruct
-// Load %ecx with the pointer to storage for the return value
-		mov ecx, [ebp+24]
-		mov [ecx+0], eax
-		mov [ecx+4], edx
-
-sc_retstruct:
-// Nothing to do!
-
-sc_noretval:
-sc_epilogue:
-		mov eax, esi
-		pop esi // NEW restore: must be preserved across function calls
-		mov esp, ebp
-		pop ebp
-		ret
-	}
-}
diff --git a/c/libffi_x86_x64/win64.asm b/c/libffi_x86_x64/win64.asm
deleted file mode 100644
index 301188b..0000000
--- a/c/libffi_x86_x64/win64.asm
+++ /dev/null
@@ -1,156 +0,0 @@
-PUBLIC	ffi_call_AMD64
-
-EXTRN	__chkstk:NEAR
-EXTRN	ffi_closure_SYSV:NEAR
-
-_TEXT	SEGMENT
-
-;;; ffi_closure_OUTER will be called with these registers set:
-;;;    rax points to 'closure'
-;;;    r11 contains a bit mask that specifies which of the
-;;;    first four parameters are float or double
-;;;
-;;; It must move the parameters passed in registers to their stack location,
-;;; call ffi_closure_SYSV for the actual work, then return the result.
-;;; 
-ffi_closure_OUTER PROC FRAME
-	;; save actual arguments to their stack space.
-	test	r11, 1
-	jne	first_is_float	
-	mov	QWORD PTR [rsp+8], rcx
-	jmp	second
-first_is_float:
-	movlpd	QWORD PTR [rsp+8], xmm0
-
-second:
-	test	r11, 2
-	jne	second_is_float	
-	mov	QWORD PTR [rsp+16], rdx
-	jmp	third
-second_is_float:
-	movlpd	QWORD PTR [rsp+16], xmm1
-
-third:
-	test	r11, 4
-	jne	third_is_float	
-	mov	QWORD PTR [rsp+24], r8
-	jmp	forth
-third_is_float:
-	movlpd	QWORD PTR [rsp+24], xmm2
-
-forth:
-	test	r11, 8
-	jne	forth_is_float	
-	mov	QWORD PTR [rsp+32], r9
-	jmp	done
-forth_is_float:
-	movlpd	QWORD PTR [rsp+32], xmm3
-
-done:
-.ALLOCSTACK 40
-	sub	rsp, 40
-.ENDPROLOG
-	mov	rcx, rax	; context is first parameter
-	mov	rdx, rsp	; stack is second parameter
-	add	rdx, 40		; correct our own area
-	mov	rax, ffi_closure_SYSV
-	call	rax		; call the real closure function
-	;; Here, code is missing that handles float return values
-	add	rsp, 40
-	movd	xmm0, rax	; In case the closure returned a float.
-	ret	0
-ffi_closure_OUTER ENDP
-
-
-;;; ffi_call_AMD64
-
-stack$ = 0
-prepfunc$ = 32
-ecif$ = 40
-bytes$ = 48
-flags$ = 56
-rvalue$ = 64
-fn$ = 72
-
-ffi_call_AMD64 PROC FRAME
-
-	mov	QWORD PTR [rsp+32], r9
-	mov	QWORD PTR [rsp+24], r8
-	mov	QWORD PTR [rsp+16], rdx
-	mov	QWORD PTR [rsp+8], rcx
-.PUSHREG rbp
-	push	rbp
-.ALLOCSTACK 48
-	sub	rsp, 48					; 00000030H
-.SETFRAME rbp, 32
-	lea	rbp, QWORD PTR [rsp+32]
-.ENDPROLOG
-
-	mov	eax, DWORD PTR bytes$[rbp]
-	add	rax, 15
-	and	rax, -16
-	call	__chkstk
-	sub	rsp, rax
-	lea	rax, QWORD PTR [rsp+32]
-	mov	QWORD PTR stack$[rbp], rax
-
-	mov	rdx, QWORD PTR ecif$[rbp]
-	mov	rcx, QWORD PTR stack$[rbp]
-	call	QWORD PTR prepfunc$[rbp]
-
-	mov	rsp, QWORD PTR stack$[rbp]
-
-	movlpd	xmm3, QWORD PTR [rsp+24]
-	movd	r9, xmm3
-
-	movlpd	xmm2, QWORD PTR [rsp+16]
-	movd	r8, xmm2
-
-	movlpd	xmm1, QWORD PTR [rsp+8]
-	movd	rdx, xmm1
-
-	movlpd	xmm0, QWORD PTR [rsp]
-	movd	rcx, xmm0
-
-	call	QWORD PTR fn$[rbp]
-ret_int$:
- 	cmp	DWORD PTR flags$[rbp], 1 ; FFI_TYPE_INT
- 	jne	ret_float$
-
-	mov	rcx, QWORD PTR rvalue$[rbp]
-	mov	DWORD PTR [rcx], eax
-	jmp	SHORT ret_nothing$
-
-ret_float$:
- 	cmp	DWORD PTR flags$[rbp], 2 ; FFI_TYPE_FLOAT
- 	jne	SHORT ret_double$
-
- 	mov	rax, QWORD PTR rvalue$[rbp]
- 	movlpd	QWORD PTR [rax], xmm0
- 	jmp	SHORT ret_nothing$
-
-ret_double$:
- 	cmp	DWORD PTR flags$[rbp], 3 ; FFI_TYPE_DOUBLE
- 	jne	SHORT ret_int64$
-
- 	mov	rax, QWORD PTR rvalue$[rbp]
- 	movlpd	QWORD PTR [rax], xmm0
- 	jmp	SHORT ret_nothing$
-
-ret_int64$:
-  	cmp	DWORD PTR flags$[rbp], 12 ; FFI_TYPE_SINT64
-  	jne	ret_nothing$
-
- 	mov	rcx, QWORD PTR rvalue$[rbp]
- 	mov	QWORD PTR [rcx], rax
- 	jmp	SHORT ret_nothing$
-	
-ret_nothing$:
-	xor	eax, eax
-
-	lea	rsp, QWORD PTR [rbp+16]
-	pop	rbp
-	ret	0
-ffi_call_AMD64 ENDP
-_TEXT	ENDS
-END
diff --git a/c/libffi_x86_x64/win64.obj b/c/libffi_x86_x64/win64.obj
deleted file mode 100644
index 38d3cd1..0000000
--- a/c/libffi_x86_x64/win64.obj
+++ /dev/null
Binary files differ
diff --git a/c/malloc_closure.h b/c/malloc_closure.h
deleted file mode 100644
index bebb93d..0000000
--- a/c/malloc_closure.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * This file is from CPython's Modules/_ctypes/malloc_closure.c
- * and has received some edits.
- */
-
-#include <ffi.h>
-#ifdef MS_WIN32
-#include <windows.h>
-#else
-#include <sys/mman.h>
-#include <unistd.h>
-# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
-#  define MAP_ANONYMOUS MAP_ANON
-# endif
-#endif
-
-/* On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC.
-
-   This is, apparently, an undocumented change to ffi_prep_closure():
-   depending on the Linux kernel we're running on, we must give it a
-   mmap that is either PROT_READ|PROT_WRITE|PROT_EXEC or only
-   PROT_READ|PROT_WRITE.  In the latter case, just trying to obtain a
-   mmap with PROT_READ|PROT_WRITE|PROT_EXEC would kill our process(!),
-   but in that situation libffi is fine with only PROT_READ|PROT_WRITE.
-   There is nothing in the libffi API to know that, though, so we have
-   to guess by parsing /proc/self/status.  "Meh."
- */
-#ifdef __linux__
-#include <stdlib.h>
-
-static int emutramp_enabled = -1;
-
-static int
-emutramp_enabled_check (void)
-{
-    char *buf = NULL;
-    size_t len = 0;
-    FILE *f;
-    int ret;
-    f = fopen ("/proc/self/status", "r");
-    if (f == NULL)
-        return 0;
-    ret = 0;
-
-    while (getline (&buf, &len, f) != -1)
-        if (!strncmp (buf, "PaX:", 4))
-            {
-                char emutramp;
-                if (sscanf (buf, "%*s %*c%c", &emutramp) == 1)
-                    ret = (emutramp == 'E');
-                break;
-            }
-    free (buf);
-    fclose (f);
-    return ret;
-}
-
-#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
-        : (emutramp_enabled = emutramp_enabled_check ()))
-#else
-#define is_emutramp_enabled() 0
-#endif
-
-
-/* 'allocate_num_pages' is dynamically adjusted starting from one
-   page.  It grows by a factor of PAGE_ALLOCATION_GROWTH_RATE.  This is
-   meant to handle both the common case of not needing a lot of pages,
-   and the rare case of needing many of them.  Systems in general have a
-   limit of how many mmap'd blocks can be open.
-*/
-
-#define PAGE_ALLOCATION_GROWTH_RATE  1.3
-
-static Py_ssize_t allocate_num_pages = 0;
-
-/* #define MALLOC_CLOSURE_DEBUG */ /* enable for some debugging output */
-
-/******************************************************************/
-
-union mmaped_block {
-    ffi_closure closure;
-    union mmaped_block *next;
-};
-
-static union mmaped_block *free_list = 0;
-static Py_ssize_t _pagesize = 0;
-
-static void more_core(void)
-{
-    union mmaped_block *item;
-    Py_ssize_t count, i;
-
-/* determine the pagesize */
-#ifdef MS_WIN32
-    if (!_pagesize) {
-        SYSTEM_INFO systeminfo;
-        GetSystemInfo(&systeminfo);
-        _pagesize = systeminfo.dwPageSize;
-    }
-#else
-    if (!_pagesize) {
-#ifdef _SC_PAGESIZE
-        _pagesize = sysconf(_SC_PAGESIZE);
-#else
-        _pagesize = getpagesize();
-#endif
-    }
-#endif
-    if (_pagesize <= 0)
-        _pagesize = 4096;
-
-    /* bump 'allocate_num_pages' */
-    allocate_num_pages = 1 + (
-        (Py_ssize_t)(allocate_num_pages * PAGE_ALLOCATION_GROWTH_RATE));
-
-    /* calculate the number of mmaped_blocks to allocate */
-    count = (allocate_num_pages * _pagesize) / sizeof(union mmaped_block);
-
-    /* allocate a memory block */
-#ifdef MS_WIN32
-    item = (union mmaped_block *)VirtualAlloc(NULL,
-                                           count * sizeof(union mmaped_block),
-                                           MEM_COMMIT,
-                                           PAGE_EXECUTE_READWRITE);
-    if (item == NULL)
-        return;
-#else
-    {
-    int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
-    if (is_emutramp_enabled ())
-        prot &= ~PROT_EXEC;
-    item = (union mmaped_block *)mmap(NULL,
-                        allocate_num_pages * _pagesize,
-                        prot,
-                        MAP_PRIVATE | MAP_ANONYMOUS,
-                        -1,
-                        0);
-    if (item == (void *)MAP_FAILED)
-        return;
-    }
-#endif
-
-#ifdef MALLOC_CLOSURE_DEBUG
-    printf("block at %p allocated (%ld bytes), %ld mmaped_blocks\n",
-           item, (long)(allocate_num_pages * _pagesize), (long)count);
-#endif
-    /* put them into the free list */
-    for (i = 0; i < count; ++i) {
-        item->next = free_list;
-        free_list = item;
-        ++item;
-    }
-}
-
-/******************************************************************/
-
-/* put the item back into the free list */
-static void cffi_closure_free(ffi_closure *p)
-{
-    union mmaped_block *item = (union mmaped_block *)p;
-    item->next = free_list;
-    free_list = item;
-}
-
-/* return one item from the free list, allocating more if needed */
-static ffi_closure *cffi_closure_alloc(void)
-{
-    union mmaped_block *item;
-    if (!free_list)
-        more_core();
-    if (!free_list)
-        return NULL;
-    item = free_list;
-    free_list = item->next;
-    return &item->closure;
-}
diff --git a/c/minibuffer.h b/c/minibuffer.h
deleted file mode 100644
index f3f5ca1..0000000
--- a/c/minibuffer.h
+++ /dev/null
@@ -1,408 +0,0 @@
-
-/* Implementation of a C object with the 'buffer' or 'memoryview'
- * interface at C-level (as approriate for the version of Python we're
- * compiling for), but only a minimal but *consistent* part of the
- * 'buffer' interface at application level.
- */
-
-typedef struct {
-    PyObject_HEAD
-    char      *mb_data;
-    Py_ssize_t mb_size;
-    PyObject  *mb_keepalive;
-    PyObject  *mb_weakreflist;    /* weakref support */
-} MiniBufferObj;
-
-static Py_ssize_t mb_length(MiniBufferObj *self)
-{
-    return self->mb_size;
-}
-
-static PyObject *mb_item(MiniBufferObj *self, Py_ssize_t idx)
-{
-    if (idx < 0 || idx >= self->mb_size ) {
-        PyErr_SetString(PyExc_IndexError, "buffer index out of range");
-        return NULL;
-    }
-    return PyBytes_FromStringAndSize(self->mb_data + idx, 1);
-}
-
-static PyObject *mb_slice(MiniBufferObj *self,
-                          Py_ssize_t left, Py_ssize_t right)
-{
-    Py_ssize_t size = self->mb_size;
-    if (left < 0)     left = 0;
-    if (right > size) right = size;
-    if (left > right) left = right;
-    return PyBytes_FromStringAndSize(self->mb_data + left, right - left);
-}
-
-static int mb_ass_item(MiniBufferObj *self, Py_ssize_t idx, PyObject *other)
-{
-    if (idx < 0 || idx >= self->mb_size) {
-        PyErr_SetString(PyExc_IndexError,
-                        "buffer assignment index out of range");
-        return -1;
-    }
-    if (PyBytes_Check(other) && PyBytes_GET_SIZE(other) == 1) {
-        self->mb_data[idx] = PyBytes_AS_STRING(other)[0];
-        return 0;
-    }
-    else {
-        PyErr_Format(PyExc_TypeError,
-                     "must assign a "STR_OR_BYTES
-                     " of length 1, not %.200s", Py_TYPE(other)->tp_name);
-        return -1;
-    }
-}
-
-/* forward: from _cffi_backend.c */
-static int _fetch_as_buffer(PyObject *x, Py_buffer *view, int writable_only);
-
-static int mb_ass_slice(MiniBufferObj *self,
-                        Py_ssize_t left, Py_ssize_t right, PyObject *other)
-{
-    Py_ssize_t count;
-    Py_ssize_t size = self->mb_size;
-    Py_buffer src_view;
-
-    if (_fetch_as_buffer(other, &src_view, 0) < 0)
-        return -1;
-
-    if (left < 0)     left = 0;
-    if (right > size) right = size;
-    if (left > right) left = right;
-
-    count = right - left;
-    if (count != src_view.len) {
-        PyBuffer_Release(&src_view);
-        PyErr_SetString(PyExc_ValueError,
-                        "right operand length must match slice length");
-        return -1;
-    }
-    memcpy(self->mb_data + left, src_view.buf, count);
-    PyBuffer_Release(&src_view);
-    return 0;
-}
-
-#if PY_MAJOR_VERSION < 3
-static Py_ssize_t mb_getdata(MiniBufferObj *self, Py_ssize_t idx, void **pp)
-{
-    *pp = self->mb_data;
-    return self->mb_size;
-}
-
-static Py_ssize_t mb_getsegcount(MiniBufferObj *self, Py_ssize_t *lenp)
-{
-    if (lenp)
-        *lenp = self->mb_size;
-    return 1;
-}
-
-static PyObject *mb_str(MiniBufferObj *self)
-{
-    /* Python 2: we want str(buffer) to behave like buffer[:], because
-       that's what bytes(buffer) does on Python 3 and there is no way
-       we can prevent this. */
-    return PyString_FromStringAndSize(self->mb_data, self->mb_size);
-}
-#endif
-
-static int mb_getbuf(MiniBufferObj *self, Py_buffer *view, int flags)
-{
-    return PyBuffer_FillInfo(view, (PyObject *)self,
-                             self->mb_data, self->mb_size,
-                             /*readonly=*/0, flags);
-}
-
-static PySequenceMethods mb_as_sequence = {
-    (lenfunc)mb_length, /*sq_length*/
-    (binaryfunc)0, /*sq_concat*/
-    (ssizeargfunc)0, /*sq_repeat*/
-    (ssizeargfunc)mb_item, /*sq_item*/
-    (ssizessizeargfunc)mb_slice, /*sq_slice*/
-    (ssizeobjargproc)mb_ass_item, /*sq_ass_item*/
-    (ssizessizeobjargproc)mb_ass_slice, /*sq_ass_slice*/
-};
-
-static PyBufferProcs mb_as_buffer = {
-#if PY_MAJOR_VERSION < 3
-    (readbufferproc)mb_getdata,
-    (writebufferproc)mb_getdata,
-    (segcountproc)mb_getsegcount,
-    (charbufferproc)mb_getdata,
-#endif
-    (getbufferproc)mb_getbuf,
-    (releasebufferproc)0,
-};
-
-static void
-mb_dealloc(MiniBufferObj *ob)
-{
-    PyObject_GC_UnTrack(ob);
-    if (ob->mb_weakreflist != NULL)
-        PyObject_ClearWeakRefs((PyObject *)ob);
-    Py_XDECREF(ob->mb_keepalive);
-    Py_TYPE(ob)->tp_free((PyObject *)ob);
-}
-
-static int
-mb_traverse(MiniBufferObj *ob, visitproc visit, void *arg)
-{
-    Py_VISIT(ob->mb_keepalive);
-    return 0;
-}
-
-static int
-mb_clear(MiniBufferObj *ob)
-{
-    Py_CLEAR(ob->mb_keepalive);
-    return 0;
-}
-
-static PyObject *
-mb_richcompare(PyObject *self, PyObject *other, int op)
-{
-    Py_ssize_t self_size, other_size;
-    Py_buffer self_bytes, other_bytes;
-    PyObject *res;
-    Py_ssize_t minsize;
-    int cmp, rc;
-
-    /* Bytes can be compared to anything that supports the (binary)
-       buffer API.  Except that a comparison with Unicode is always an
-       error, even if the comparison is for equality. */
-    rc = PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type);
-    if (!rc)
-        rc = PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type);
-    if (rc < 0)
-        return NULL;
-    if (rc) {
-        Py_INCREF(Py_NotImplemented);
-        return Py_NotImplemented;
-    }
-
-    if (PyObject_GetBuffer(self, &self_bytes, PyBUF_SIMPLE) != 0) {
-        PyErr_Clear();
-        Py_INCREF(Py_NotImplemented);
-        return Py_NotImplemented;
-
-    }
-    self_size = self_bytes.len;
-
-    if (PyObject_GetBuffer(other, &other_bytes, PyBUF_SIMPLE) != 0) {
-        PyErr_Clear();
-        PyBuffer_Release(&self_bytes);
-        Py_INCREF(Py_NotImplemented);
-        return Py_NotImplemented;
-
-    }
-    other_size = other_bytes.len;
-
-    if (self_size != other_size && (op == Py_EQ || op == Py_NE)) {
-        /* Shortcut: if the lengths differ, the objects differ */
-        cmp = (op == Py_NE);
-    }
-    else {
-        minsize = self_size;
-        if (other_size < minsize)
-            minsize = other_size;
-
-        cmp = memcmp(self_bytes.buf, other_bytes.buf, minsize);
-        /* In ISO C, memcmp() guarantees to use unsigned bytes! */
-
-        if (cmp == 0) {
-            if (self_size < other_size)
-                cmp = -1;
-            else if (self_size > other_size)
-                cmp = 1;
-        }
-
-        switch (op) {
-        case Py_LT: cmp = cmp <  0; break;
-        case Py_LE: cmp = cmp <= 0; break;
-        case Py_EQ: cmp = cmp == 0; break;
-        case Py_NE: cmp = cmp != 0; break;
-        case Py_GT: cmp = cmp >  0; break;
-        case Py_GE: cmp = cmp >= 0; break;
-        }
-    }
-
-    res = cmp ? Py_True : Py_False;
-    PyBuffer_Release(&self_bytes);
-    PyBuffer_Release(&other_bytes);
-    Py_INCREF(res);
-    return res;
-}
-
-#if PY_MAJOR_VERSION >= 3
-/* pfffffffffffff pages of copy-paste from listobject.c */
-
-/* pfffffffffffff#2: the PySlice_GetIndicesEx() *macro* should not
-   be called, because C extension modules compiled with it differ
-   on ABI between 3.6.0, 3.6.1 and 3.6.2. */
-#if PY_VERSION_HEX < 0x03070000 && defined(PySlice_GetIndicesEx) && !defined(PYPY_VERSION)
-#undef PySlice_GetIndicesEx
-#endif
-
-static PyObject *mb_subscript(MiniBufferObj *self, PyObject *item)
-{
-    if (PyIndex_Check(item)) {
-        Py_ssize_t i;
-        i = PyNumber_AsSsize_t(item, PyExc_IndexError);
-        if (i == -1 && PyErr_Occurred())
-            return NULL;
-        if (i < 0)
-            i += self->mb_size;
-        return mb_item(self, i);
-    }
-    else if (PySlice_Check(item)) {
-        Py_ssize_t start, stop, step, slicelength;
-
-        if (PySlice_GetIndicesEx(item, self->mb_size,
-                         &start, &stop, &step, &slicelength) < 0)
-            return NULL;
-
-        if (step == 1)
-            return mb_slice(self, start, stop);
-        else {
-            PyErr_SetString(PyExc_TypeError,
-                            "buffer doesn't support slicing with step != 1");
-            return NULL;
-        }
-    }
-    else {
-        PyErr_Format(PyExc_TypeError,
-                     "buffer indices must be integers, not %.200s",
-                     item->ob_type->tp_name);
-        return NULL;
-    }
-}
-static int
-mb_ass_subscript(MiniBufferObj* self, PyObject* item, PyObject* value)
-{
-    if (PyIndex_Check(item)) {
-        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
-        if (i == -1 && PyErr_Occurred())
-            return -1;
-        if (i < 0)
-            i += self->mb_size;
-        return mb_ass_item(self, i, value);
-    }
-    else if (PySlice_Check(item)) {
-        Py_ssize_t start, stop, step, slicelength;
-
-        if (PySlice_GetIndicesEx(item, self->mb_size,
-                         &start, &stop, &step, &slicelength) < 0) {
-            return -1;
-        }
-
-        if (step == 1)
-            return mb_ass_slice(self, start, stop, value);
-        else {
-            PyErr_SetString(PyExc_TypeError,
-                            "buffer doesn't support slicing with step != 1");
-            return -1;
-        }
-    }
-    else {
-        PyErr_Format(PyExc_TypeError,
-                     "buffer indices must be integers, not %.200s",
-                     item->ob_type->tp_name);
-        return -1;
-    }
-}
-
-static PyMappingMethods mb_as_mapping = {
-    (lenfunc)mb_length, /*mp_length*/
-    (binaryfunc)mb_subscript, /*mp_subscript*/
-    (objobjargproc)mb_ass_subscript, /*mp_ass_subscript*/
-};
-#endif
-
-#if PY_MAJOR_VERSION >= 3
-# define MINIBUF_TPFLAGS 0
-#else
-# define MINIBUF_TPFLAGS (Py_TPFLAGS_HAVE_GETCHARBUFFER | Py_TPFLAGS_HAVE_NEWBUFFER)
-#endif
-
-PyDoc_STRVAR(ffi_buffer_doc,
-"ffi.buffer(cdata[, byte_size]):\n"
-"Return a read-write buffer object that references the raw C data\n"
-"pointed to by the given 'cdata'.  The 'cdata' must be a pointer or an\n"
-"array.  Can be passed to functions expecting a buffer, or directly\n"
-"manipulated with:\n"
-"\n"
-"    buf[:]          get a copy of it in a regular string, or\n"
-"    buf[idx]        as a single character\n"
-"    buf[:] = ...\n"
-"    buf[idx] = ...  change the content");
-
-static PyObject *            /* forward, implemented in _cffi_backend.c */
-b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-
-static PyTypeObject MiniBuffer_Type = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    "_cffi_backend.buffer",
-    sizeof(MiniBufferObj),
-    0,
-    (destructor)mb_dealloc,                     /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-    0,                                          /* tp_compare */
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    &a