Author: Armin Rigo <[email protected]>
Branch:
Changeset: r128:25439df4dc03
Date: 2014-11-30 11:15 +0100
http://bitbucket.org/cffi/creflect/changeset/25439df4dc03/
Log: Split zeffir.c into pieces, to avoid ending up like _cffi_backend.c
diff --git a/zeffir/test/test_basic.py b/zeffir/test/test_basic.py
--- a/zeffir/test/test_basic.py
+++ b/zeffir/test/test_basic.py
@@ -33,3 +33,7 @@
ffi, lib = zeffir.open('basic', relative_to=zeffir_lib_path)
assert lib.forty_two == 42
assert type(lib.forty_two) is int
+
+def test_dir():
+ ffi, lib = zeffir.open('basic', relative_to=zeffir_lib_path)
+ assert dir(lib) == ['forty_two']
diff --git a/zeffir/zef_builder.c b/zeffir/zef_builder.c
new file mode 100644
--- /dev/null
+++ b/zeffir/zef_builder.c
@@ -0,0 +1,248 @@
+
+#define MAGIC_CREFLECT_TAG 0x54822e00
+#define CREFLECT_VERSION 0x01
+
+typedef struct {
+ _crx_builder_t cb;
+ PyLibObject *lib;
+ PyFFIObject *ffi;
+ PyObject *dict;
+} zeffir_builder_t;
+
+static PyObject *zef_cache_primitive_signed;
+
+static _crx_type_t *zef_get_void_type(_crx_builder_t *cb)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_char_type(_crx_builder_t *cb)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_bool_type(_crx_builder_t *cb)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_signed_type(_crx_builder_t *cb, size_t sz,
+ const char *name)
+{
+ PyObject *x = PyDict_GetItemString(zef_cache_primitive_signed, name);
+ CTypeDescrObject *td = (CTypeDescrObject *)x;
+
+ if (td == NULL) {
+ int err;
+ size_t name_length = strlen(name);
+
+ td = ctypedescr_new(name_length + 1);
+ if (td == NULL)
+ return NULL;
+
+ memcpy(td->ct_name, name, name_length + 1);
+ td->ct_name_position = name_length;
+ td->ct_size = sz;
+ //td->ct_length = ptypes->align;
+ //td->ct_extra = ffitype;
+ td->ct_flags = CT_PRIMITIVE_SIGNED;
+ if (td->ct_size <= sizeof(long))
+ td->ct_flags |= CT_PRIMITIVE_FITS_LONG;
+
+ x = (PyObject *)td;
+ err = PyDict_SetItemString(zef_cache_primitive_signed, name, x);
+ Py_DECREF(x);
+ if (err < 0)
+ return NULL;
+ }
+ return td;
+}
+
+static _crx_type_t *zef_get_unsigned_type(_crx_builder_t *cb, size_t sz,
+ const char *g)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_float_type(_crx_builder_t *cb, size_t sz,
+ const char *g)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_function_type(_crx_builder_t *cb, _crx_type_t *ret,
+ _crx_type_t *args[], int nargs,
+ _crx_trampoline1_fn trampl)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_ellipsis_function_type(_crx_builder_t *cb,
+ _crx_type_t *ret,
+ _crx_type_t *args[],
+ int nargs)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_pointer_type(_crx_builder_t *cb, _crx_type_t *t)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_const_type(_crx_builder_t *cb, _crx_type_t *t)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_array_type(_crx_builder_t *cb, _crx_type_t *t,
+ size_t len)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_incomplete_array_type(_crx_builder_t *cb,
+ _crx_type_t *t)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_struct_type(_crx_builder_t *cb, const char *name)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_union_type(_crx_builder_t *cb, const char *name)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_enum_type(_crx_builder_t *cb, const char *name)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_user_type(_crx_builder_t *cb, const char *name)
+{
+ abort();
+}
+
+static _crx_type_t *zef_get_unknown_type(_crx_builder_t *cb, const char *name)
+{
+ abort();
+}
+
+static void zef_complete(_crx_builder_t *cb, _crx_type_t *t,
+ size_t sz, size_t align,
+ _crx_field_t fields[], int nfields)
+{
+ abort();
+}
+
+static void zef_complete_enum(_crx_builder_t *cb, _crx_type_t *t,
+ _crx_type_t *inttype)
+{
+ abort();
+}
+
+static void zef_define_type(_crx_builder_t *cb, const char *name,
+ _crx_type_t *t)
+{
+ abort();
+}
+
+static void zef_define_var(_crx_builder_t *cb, const char *name,
+ _crx_type_t *t, void *addr)
+{
+ abort();
+}
+
+static void zef_define_func(_crx_builder_t *cb, const char *name,
+ _crx_type_t *ret, _crx_type_t *args[], int nargs,
+ _crx_trampoline0_fn trampl, void *directcall)
+{
+ abort();
+}
+
+static void zef_define_num_const(_crx_builder_t *cb, const char *name,
+ _crx_type_t *t, _crx_num_const_t *value)
+{
+ PyObject *dict = ((zeffir_builder_t *)cb)->dict;
+
+ PyObject *x = PyInt_FromLong(value->as_int);
+ if (x == NULL)
+ return;
+
+ PyDict_SetItemString(dict, name, x);
+ Py_DECREF(x);
+}
+
+static void zef_error(_crx_builder_t *cb, const char *msg)
+{
+ abort();
+}
+
+static int load_creflect_main(PyLibObject *lib)
+{
+ const char *creflect_main = "_creflect_main"; /* XXX fixed for now */
+ int (*crxmain)(_crx_builder_t *);
+ crxmain = (int(*)(_crx_builder_t *))dlsym(lib->ffi->dl_lib, creflect_main);
+ if (crxmain == NULL) {
+ PyErr_Format(PyExc_OSError, "%s: symbol '%s' not found",
+ lib->ffi->libname, creflect_main);
+ return -1;
+ }
+
+ int result = crxmain(NULL);
+ if ((result & ~0xFF) != MAGIC_CREFLECT_TAG) {
+ PyErr_Format(PyExc_OSError, "%s: %s() is not a creflect entry point",
+ lib->ffi->libname, creflect_main);
+ return -1;
+ }
+ if ((result & 0xFF) != CREFLECT_VERSION) {
+ PyErr_Format(PyExc_OSError, "%s was made with creflect version %d, "
+ "expected %d", lib->ffi->libname, result & 0xFF,
+ CREFLECT_VERSION);
+ return -1;
+ }
+
+ zeffir_builder_t builder = {
+ {
+ zef_get_void_type,
+ zef_get_char_type,
+ zef_get_bool_type,
+ zef_get_signed_type,
+ zef_get_unsigned_type,
+ zef_get_float_type,
+ zef_get_function_type,
+ zef_get_ellipsis_function_type,
+ zef_get_pointer_type,
+ zef_get_const_type,
+ zef_get_array_type,
+ zef_get_incomplete_array_type,
+ zef_get_struct_type,
+ zef_get_union_type,
+ zef_get_enum_type,
+ zef_get_user_type,
+ zef_get_unknown_type,
+ zef_complete,
+ zef_complete_enum,
+ zef_define_type,
+ zef_define_var,
+ zef_define_func,
+ zef_define_num_const,
+ zef_error,
+ },
+ lib, /* lib */
+ lib->ffi, /* ffi */
+ lib->dict, /* dict */
+ };
+ crxmain(&builder.cb);
+ return PyErr_Occurred() ? -1 : 0;
+}
+
+static void init_caches(void)
+{
+ if ((zef_cache_primitive_signed = PyDict_New()) == NULL)
+ return;
+}
diff --git a/zeffir/zef_ctype.c b/zeffir/zef_ctype.c
new file mode 100644
--- /dev/null
+++ b/zeffir/zef_ctype.c
@@ -0,0 +1,141 @@
+
+/* base type flag: exactly one of the following: */
+#define CT_PRIMITIVE_SIGNED 1 /* signed integer */
+#define CT_PRIMITIVE_UNSIGNED 2 /* unsigned integer, bool */
+#define CT_PRIMITIVE_CHAR 4 /* char */
+#define CT_PRIMITIVE_FLOAT 8 /* float, double, long double */
+#define CT_POINTER 16 /* pointer, excluding ptr-to-func */
+#define CT_ARRAY 32 /* array */
+#define CT_STRUCT 64 /* struct */
+#define CT_UNION 128 /* union */
+#define CT_FUNCTIONPTR 256 /* pointer to function */
+#define CT_VOID 512 /* void */
+
+/* other flags that may also be set in addition to the base flag: */
+#define CT_CAST_ANYTHING 1024 /* 'char *' and 'void *' only */
+#define CT_PRIMITIVE_FITS_LONG 2048
+#define CT_IS_OPAQUE 4096
+#define CT_IS_ENUM 8192
+#define CT_IS_PTR_TO_OWNED 16384
+#define CT_IS_LONGDOUBLE 65536
+#define CT_IS_BOOL 131072
+#define CT_IS_VOID_PTR 524288
+#define CT_WITH_VAR_ARRAY 1048576
+#define CT_PRIMITIVE_ANY (CT_PRIMITIVE_SIGNED | \
+ CT_PRIMITIVE_UNSIGNED | \
+ CT_PRIMITIVE_CHAR | \
+ CT_PRIMITIVE_FLOAT)
+
+struct _crx_type_s {
+ PyObject_VAR_HEAD
+
+ CTypeDescrObject *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 */
+
+ Py_ssize_t ct_size; /* size of instances, or -1 if unknown */
+ Py_ssize_t ct_length; /* length of arrays, or -1 if unknown */
+ 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 */
+};
+
+static PyTypeObject CTypeDescr_Type;
+//static PyTypeObject CField_Type;
+//static PyTypeObject CData_Type;
+//static PyTypeObject CDataOwning_Type;
+//static PyTypeObject CDataOwningGC_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)
+#define CDataOwn_Check(ob) (Py_TYPE(ob) == &CDataOwning_Type || \
+ Py_TYPE(ob) == &CDataOwningGC_Type)
+
+/************************************************************/
+
+static CTypeDescrObject *ctypedescr_new(size_t 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_size = -1;
+ ct->ct_length = -1;
+ PyObject_GC_Track(ct);
+ return ct;
+}
+
+static void ctypedescr_dealloc(CTypeDescrObject *ct)
+{
+ PyObject_GC_UnTrack(ct);
+ if (ct->ct_weakreflist != NULL)
+ PyObject_ClearWeakRefs((PyObject *) ct);
+ 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 PyTypeObject CTypeDescr_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "_cffi_backend.CTypeDescr",
+ offsetof(CTypeDescrObject, ct_name),
+ sizeof(char),
+ (destructor)ctypedescr_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0,//(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 */
+ 0,//ctypedescr_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0,//ctypedescr_getsets, /* tp_getset */
+};
diff --git a/zeffir/zef_ffi_obj.c b/zeffir/zef_ffi_obj.c
new file mode 100644
--- /dev/null
+++ b/zeffir/zef_ffi_obj.c
@@ -0,0 +1,51 @@
+
+struct PyFFIObject_s {
+ PyObject_HEAD
+ void *dl_lib;
+ char *libname;
+};
+
+static void ffi_dealloc(PyFFIObject *ffi)
+{
+ if (ffi->dl_lib != NULL)
+ dlclose(ffi->dl_lib);
+ free(ffi->libname);
+ PyObject_Del(ffi);
+}
+
+static PyObject *ffi_repr(PyFFIObject *ffi)
+{
+ return PyString_FromFormat("<zeffir.FFI object for '%s'>", ffi->libname);
+}
+
+static PyTypeObject FFI_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "zeffir.FFI",
+ sizeof(PyFFIObject),
+ 0,
+ (destructor)ffi_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)ffi_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 */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+};
diff --git a/zeffir/zef_funcs.c b/zeffir/zef_funcs.c
new file mode 100644
--- /dev/null
+++ b/zeffir/zef_funcs.c
@@ -0,0 +1,77 @@
+
+static PyObject *b_open(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ char *keywords[] = {"libname", "relative_to", NULL};
+ char *libname, *relative_to;
+ char *path;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", keywords,
+ &libname, &relative_to))
+ return NULL;
+
+ char *last_slash = strrchr(relative_to, '/');
+ if (last_slash == NULL) {
+ relative_to = "./";
+ last_slash = relative_to + 1;
+ }
+ size_t n = last_slash + 1 - relative_to;
+ path = malloc(n + strlen(libname) + 16);
+ if (path == NULL)
+ return PyErr_NoMemory();
+ memcpy(path, relative_to, n);
+ strcpy(path + n, "lib");
+ strcat(path + n, libname);
+ strcat(path + n, ".so");
+
+ PyFFIObject *ffi = NULL;
+ PyLibObject *lib = NULL;
+ PyObject *dict = NULL;
+
+ dlerror(); /* clear errors */
+ void *dl_lib = dlopen(path, RTLD_LAZY);
+ if (dl_lib == NULL) {
+ char *error = dlerror();
+ if (error == NULL)
+ error = "failed to open";
+ PyErr_Format(PyExc_OSError, "%s: %s", path, error);
+ goto error;
+ }
+
+ ffi = PyObject_New(PyFFIObject, &FFI_Type);
+ if (ffi == NULL)
+ goto error;
+ ffi->dl_lib = dl_lib; dl_lib = NULL;
+ ffi->libname = path; path = NULL;
+
+ dict = PyDict_New();
+ if (dict == NULL)
+ goto error;
+
+ lib = PyObject_New(PyLibObject, &Lib_Type);
+ if (lib == NULL)
+ goto error;
+ lib->ffi = ffi; ffi = NULL;
+ lib->dict = dict; dict = NULL;
+
+ if (load_creflect_main(lib) < 0)
+ goto error;
+
+ PyObject *result = Py_BuildValue("OO", lib->ffi, lib);
+ Py_DECREF(lib);
+ return result;
+
+ error:
+ Py_XDECREF(dict);
+ Py_XDECREF(lib);
+ Py_XDECREF(ffi);
+ if (dl_lib != NULL)
+ dlclose(dl_lib);
+ free(path);
+ return NULL;
+}
+
+
+static PyMethodDef ZeffirMethods[] = {
+ {"open", (PyCFunction)b_open, METH_KEYWORDS},
+ {NULL, NULL} /* Sentinel */
+};
diff --git a/zeffir/zef_lib_obj.c b/zeffir/zef_lib_obj.c
new file mode 100644
--- /dev/null
+++ b/zeffir/zef_lib_obj.c
@@ -0,0 +1,72 @@
+
+struct PyLibObject_s {
+ PyObject_HEAD
+ PyObject *dict;
+ PyFFIObject *ffi;
+};
+
+static void lib_dealloc(PyLibObject *lib)
+{
+ Py_DECREF(lib->dict);
+ Py_DECREF(lib->ffi);
+ PyObject_Del(lib);
+}
+
+static PyObject *lib_repr(PyLibObject *lib)
+{
+ return PyString_FromFormat("<zeffir.Lib object for '%s'>",
+ lib->ffi->libname);
+}
+
+static PyObject *lib_dir(PyObject *lib, PyObject *noarg)
+{
+ return PyDict_Keys(((PyLibObject *)lib)->dict);
+}
+
+static PyMethodDef lib_methods[] = {
+ {"__dir__", lib_dir, METH_NOARGS},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyMemberDef lib_members[] = {
+ {"__dict__", T_OBJECT, offsetof(PyLibObject, dict), READONLY},
+ {NULL}
+};
+
+static PyTypeObject Lib_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "zeffir.Lib",
+ sizeof(PyLibObject),
+ 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 */
+ 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 */
+ lib_methods, /* tp_methods */
+ lib_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ offsetof(PyLibObject, dict), /* tp_dictoffset */
+};
diff --git a/zeffir/zeffir.c b/zeffir/zeffir.c
--- a/zeffir/zeffir.c
+++ b/zeffir/zeffir.c
@@ -5,417 +5,23 @@
#include "../creflect/creflect_cdecl.h"
-#define MAGIC_CREFLECT_TAG 0x54822e00
-#define CREFLECT_VERSION 0x01
+typedef struct _crx_type_s CTypeDescrObject;
+typedef struct PyLibObject_s PyLibObject;
+typedef struct PyFFIObject_s PyFFIObject;
/************************************************************/
+/* Works by including all other .c files. */
+/* Allows all function and global symbols to remain static. */
-typedef struct {
- PyObject_HEAD
- void *dl_lib;
- char *libname;
-} PyFFIObject;
-
-static void ffi_dealloc(PyFFIObject *ffi)
-{
- if (ffi->dl_lib != NULL)
- dlclose(ffi->dl_lib);
- free(ffi->libname);
- PyObject_Del(ffi);
-}
-
-static PyObject *ffi_repr(PyFFIObject *ffi)
-{
- return PyString_FromFormat("<zeffir.FFI object for '%s'>", ffi->libname);
-}
-
-static PyTypeObject FFI_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "zeffir.FFI",
- sizeof(PyFFIObject),
- 0,
- (destructor)ffi_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)ffi_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 */
- 0, /* tp_methods */
- 0, /* tp_members */
-};
+#include "zef_ctype.c"
+#include "zef_ffi_obj.c"
+#include "zef_lib_obj.c"
+#include "zef_builder.c"
+#include "zef_funcs.c"
/************************************************************/
-typedef struct {
- PyObject_HEAD
- PyObject *dict;
- PyFFIObject *ffi;
-} PyLibObject;
-
-static PyMemberDef lib_members[] = {
- {"__dict__", T_OBJECT, offsetof(PyLibObject, dict), READONLY},
- {NULL}
-};
-
-static void lib_dealloc(PyLibObject *lib)
-{
- Py_DECREF(lib->dict);
- Py_DECREF(lib->ffi);
- PyObject_Del(lib);
-}
-
-static PyObject *lib_repr(PyLibObject *lib)
-{
- return PyString_FromFormat("<zeffir.Lib object for '%s'>",
- lib->ffi->libname);
-}
-
-static PyTypeObject Lib_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "zeffir.Lib",
- sizeof(PyLibObject),
- 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 */
- 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 */
- lib_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(PyLibObject, dict), /* tp_dictoffset */
-};
-
-/************************************************************/
-
-typedef struct {
- _crx_builder_t cb;
- PyLibObject *lib;
- PyFFIObject *ffi;
- PyObject *dict;
-} zeffir_builder_t;
-
-static _crx_type_t *zef_get_void_type(_crx_builder_t *cb)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_char_type(_crx_builder_t *cb)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_bool_type(_crx_builder_t *cb)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_signed_type(_crx_builder_t *cb, size_t sz,
- const char *g)
-{
- return NULL; // XXX
-}
-
-static _crx_type_t *zef_get_unsigned_type(_crx_builder_t *cb, size_t sz,
- const char *g)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_float_type(_crx_builder_t *cb, size_t sz,
- const char *g)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_function_type(_crx_builder_t *cb, _crx_type_t *ret,
- _crx_type_t *args[], int nargs,
- _crx_trampoline1_fn trampl)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_ellipsis_function_type(_crx_builder_t *cb,
- _crx_type_t *ret,
- _crx_type_t *args[],
- int nargs)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_pointer_type(_crx_builder_t *cb, _crx_type_t *t)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_const_type(_crx_builder_t *cb, _crx_type_t *t)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_array_type(_crx_builder_t *cb, _crx_type_t *t,
- size_t len)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_incomplete_array_type(_crx_builder_t *cb,
- _crx_type_t *t)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_struct_type(_crx_builder_t *cb, const char *name)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_union_type(_crx_builder_t *cb, const char *name)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_enum_type(_crx_builder_t *cb, const char *name)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_user_type(_crx_builder_t *cb, const char *name)
-{
- abort();
-}
-
-static _crx_type_t *zef_get_unknown_type(_crx_builder_t *cb, const char *name)
-{
- abort();
-}
-
-static void zef_complete(_crx_builder_t *cb, _crx_type_t *t,
- size_t sz, size_t align,
- _crx_field_t fields[], int nfields)
-{
- abort();
-}
-
-static void zef_complete_enum(_crx_builder_t *cb, _crx_type_t *t,
- _crx_type_t *inttype)
-{
- abort();
-}
-
-static void zef_define_type(_crx_builder_t *cb, const char *name,
- _crx_type_t *t)
-{
- abort();
-}
-
-static void zef_define_var(_crx_builder_t *cb, const char *name,
- _crx_type_t *t, void *addr)
-{
- abort();
-}
-
-static void zef_define_func(_crx_builder_t *cb, const char *name,
- _crx_type_t *ret, _crx_type_t *args[], int nargs,
- _crx_trampoline0_fn trampl, void *directcall)
-{
- abort();
-}
-
-static void zef_define_num_const(_crx_builder_t *cb, const char *name,
- _crx_type_t *t, _crx_num_const_t *value)
-{
- PyObject *dict = ((zeffir_builder_t *)cb)->dict;
-
- PyObject *x = PyInt_FromLong(value->as_int);
- if (x == NULL)
- return;
-
- PyDict_SetItemString(dict, name, x);
- Py_DECREF(x);
-}
-
-static void zef_error(_crx_builder_t *cb, const char *msg)
-{
- abort();
-}
-
-static int load_creflect_main(PyLibObject *lib)
-{
- const char *creflect_main = "_creflect_main"; /* XXX fixed for now */
- int (*crxmain)(_crx_builder_t *);
- crxmain = (int(*)(_crx_builder_t *))dlsym(lib->ffi->dl_lib, creflect_main);
- if (crxmain == NULL) {
- PyErr_Format(PyExc_OSError, "%s: symbol '%s' not found",
- lib->ffi->libname, creflect_main);
- return -1;
- }
-
- int result = crxmain(NULL);
- if ((result & ~0xFF) != MAGIC_CREFLECT_TAG) {
- PyErr_Format(PyExc_OSError, "%s: %s() is not a creflect entry point",
- lib->ffi->libname, creflect_main);
- return -1;
- }
- if ((result & 0xFF) != CREFLECT_VERSION) {
- PyErr_Format(PyExc_OSError, "%s was made with creflect version %d, "
- "expected %d", lib->ffi->libname, result & 0xFF,
- CREFLECT_VERSION);
- return -1;
- }
-
- zeffir_builder_t builder = {
- {
- zef_get_void_type,
- zef_get_char_type,
- zef_get_bool_type,
- zef_get_signed_type,
- zef_get_unsigned_type,
- zef_get_float_type,
- zef_get_function_type,
- zef_get_ellipsis_function_type,
- zef_get_pointer_type,
- zef_get_const_type,
- zef_get_array_type,
- zef_get_incomplete_array_type,
- zef_get_struct_type,
- zef_get_union_type,
- zef_get_enum_type,
- zef_get_user_type,
- zef_get_unknown_type,
- zef_complete,
- zef_complete_enum,
- zef_define_type,
- zef_define_var,
- zef_define_func,
- zef_define_num_const,
- zef_error,
- },
- lib, /* lib */
- lib->ffi, /* ffi */
- lib->dict, /* dict */
- };
- crxmain(&builder.cb);
- return PyErr_Occurred() ? -1 : 0;
-}
-
-static PyObject *b_open(PyObject *self, PyObject *args, PyObject *kwds)
-{
- char *keywords[] = {"libname", "relative_to", NULL};
- char *libname, *relative_to;
- char *path;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", keywords,
- &libname, &relative_to))
- return NULL;
-
- char *last_slash = strrchr(relative_to, '/');
- if (last_slash == NULL) {
- relative_to = "./";
- last_slash = relative_to + 1;
- }
- size_t n = last_slash + 1 - relative_to;
- path = malloc(n + strlen(libname) + 16);
- if (path == NULL)
- return PyErr_NoMemory();
- memcpy(path, relative_to, n);
- strcpy(path + n, "lib");
- strcat(path + n, libname);
- strcat(path + n, ".so");
-
- PyFFIObject *ffi = NULL;
- PyLibObject *lib = NULL;
- PyObject *dict = NULL;
-
- dlerror(); /* clear errors */
- void *dl_lib = dlopen(path, RTLD_LAZY);
- if (dl_lib == NULL) {
- char *error = dlerror();
- if (error == NULL)
- error = "failed to open";
- PyErr_Format(PyExc_OSError, "%s: %s", path, error);
- goto error;
- }
-
- ffi = PyObject_New(PyFFIObject, &FFI_Type);
- if (ffi == NULL)
- goto error;
- ffi->dl_lib = dl_lib; dl_lib = NULL;
- ffi->libname = path; path = NULL;
-
- dict = PyDict_New();
- if (dict == NULL)
- goto error;
-
- lib = PyObject_New(PyLibObject, &Lib_Type);
- if (lib == NULL)
- goto error;
- lib->ffi = ffi; ffi = NULL;
- lib->dict = dict; dict = NULL;
-
- if (load_creflect_main(lib) < 0)
- goto error;
-
- PyObject *result = Py_BuildValue("OO", lib->ffi, lib);
- Py_DECREF(lib);
- return result;
-
- error:
- Py_XDECREF(dict);
- Py_XDECREF(lib);
- Py_XDECREF(ffi);
- if (dl_lib != NULL)
- dlclose(dl_lib);
- free(path);
- return NULL;
-}
-
-
-static PyMethodDef ZeffirMethods[] = {
- {"open", (PyCFunction)b_open, METH_KEYWORDS},
- {NULL, NULL} /* Sentinel */
-};
-
PyMODINIT_FUNC
initzeffir(void)
{
@@ -424,6 +30,12 @@
m = Py_InitModule("zeffir", ZeffirMethods);
(void)m;
- PyType_Ready(&FFI_Type);
- PyType_Ready(&Lib_Type);
+ init_caches();
+ if (PyErr_Occurred())
+ return;
+
+ if (PyType_Ready(&FFI_Type) < 0)
+ return;
+ if (PyType_Ready(&Lib_Type) < 0)
+ return;
}
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit