[pypy-commit] cffi cffi-1.0: Just enough to pass this small demo
arigo
noreply at buildbot.pypy.org
Mon May 11 17:24:08 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1975:dbbbc44e0a15
Date: 2015-05-11 17:24 +0200
http://bitbucket.org/cffi/cffi/changeset/dbbbc44e0a15/
Log: Just enough to pass this small demo
diff --git a/_cffi1/cdlopen.c b/_cffi1/cdlopen.c
--- a/_cffi1/cdlopen.c
+++ b/_cffi1/cdlopen.c
@@ -20,6 +20,12 @@
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) {
@@ -31,7 +37,38 @@
return 0;
}
+static PyObject *ffi_dlopen(PyObject *self, PyObject *args)
+{
+ char *filename_or_null, *printable_filename;
+ void *handle;
+ int flags = 0;
+ 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;
+ }
+ else if (!PyArg_ParseTuple(args, "et|i:load_library",
+ Py_FileSystemDefaultEncoding, &filename_or_null,
+ &flags))
+ return NULL;
+
+ if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0)
+ flags |= RTLD_NOW;
+ printable_filename = filename_or_null ? filename_or_null : "<None>";
+
+ handle = dlopen(filename_or_null, flags);
+ if (handle == NULL) {
+ const char *error = dlerror();
+ PyErr_Format(PyExc_OSError, "cannot load library '%s': %s",
+ printable_filename, error);
+ return NULL;
+ }
+ return (PyObject *)lib_internal_new((FFIObject *)self,
+ printable_filename, handle);
+}
static PyObject *ffi_dlclose(PyObject *self, PyObject *args)
{
@@ -56,3 +93,101 @@
Py_INCREF(Py_None);
return Py_None;
}
+
+
+static int cdl_int(char *src)
+{
+ unsigned char *usrc = (unsigned char *)src;
+ return (usrc[0] << 24) | (usrc[1] << 16) | (usrc[2] << 8) | usrc[3];
+}
+
+static _cffi_opcode_t cdl_opcode(char *src)
+{
+ return (_cffi_opcode_t)(Py_ssize_t)cdl_int(src);
+}
+
+static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ FFIObject *ffi;
+ static char *keywords[] = {"module_name", "_version", "_types",
+ "_globals", "_struct_unions", "_enums",
+ "_typenames", "_consts", NULL};
+ char *ffiname = NULL, *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, *consts = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sns#O!OOOO:FFI", keywords,
+ &ffiname, &version, &types, &types_len,
+ &PyTuple_Type, &globals,
+ &struct_unions, &enums,
+ &typenames, &consts))
+ 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 (types_len > 0) {
+ _cffi_opcode_t *ntypes;
+ Py_ssize_t i, n = types_len / 4; /* 4 bytes entries */
+
+ 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;
+ building = NULL;
+ }
+
+ if (globals != NULL) {
+ struct _cffi_global_s *nglob;
+ Py_ssize_t i, n = PyTuple_GET_SIZE(globals);
+
+ building = PyMem_Malloc(n * sizeof(struct _cffi_global_s));
+ if (building == NULL)
+ goto error;
+ memset(building, 0, n * sizeof(struct _cffi_global_s));
+ nglob = (struct _cffi_global_s *)building;
+
+ for (i = 0; i < n; i++) {
+ char *g = PyString_AS_STRING(PyTuple_GET_ITEM(globals, i));
+ nglob[i].type_op = cdl_opcode(g);
+ nglob[i].name = g + 4;
+ }
+ ffi->types_builder.ctx.globals = nglob;
+ ffi->types_builder.ctx.num_globals = n;
+ building = NULL;
+ }
+
+ if (consts != NULL) {
+ Py_INCREF(consts);
+ ffi->types_builder.known_constants = consts;
+ }
+
+ /* 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/_cffi1/ffi_obj.c b/_cffi1/ffi_obj.c
--- a/_cffi1/ffi_obj.c
+++ b/_cffi1/ffi_obj.c
@@ -83,35 +83,8 @@
return (PyObject *)ffi_internal_new(type, NULL);
}
-static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- FFIObject *ffi;
- static char *keywords[] = {"module_name", "_version", "_types",
- "_globals", "_struct_unions", "_enums",
- "_typenames", "_consts", NULL};
- char *ffiname = NULL, *types = NULL;
- Py_ssize_t version = -1;
- Py_ssize_t types_len = 0;
- PyObject *globals = NULL, *struct_unions = NULL, *enums = NULL;
- PyObject *typenames = NULL, *consts = NULL;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sns#OOOOO:FFI", keywords,
- &ffiname, &version, &types, &types_len,
- &globals, &struct_unions, &enums,
- &typenames, &consts))
- 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;
- return 0;
-}
+/* forward, declared in cdlopen.c because it's mostly useful for this case */
+static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds);
#define ACCEPT_STRING 1
#define ACCEPT_CTYPE 2
diff --git a/_cffi1/lib_obj.c b/_cffi1/lib_obj.c
--- a/_cffi1/lib_obj.c
+++ b/_cffi1/lib_obj.c
@@ -72,15 +72,12 @@
return result;
}
-static int cdlopen_close(PyObject *libname, void *libhandle); /* forward */
+static void cdlopen_close_ignore_errors(void *libhandle); /* forward */
static void *cdlopen_fetch(PyObject *libname, void *libhandle, char *symbol);
static void lib_dealloc(LibObject *lib)
{
- if (cdlopen_close(lib->l_libname, lib->l_libhandle) < 0) {
- PyErr_WriteUnraisable((PyObject *)lib);
- PyErr_Clear();
- }
+ cdlopen_close_ignore_errors(lib->l_libhandle);
Py_DECREF(lib->l_dict);
Py_DECREF(lib->l_libname);
Py_XDECREF(lib->l_includes);
@@ -208,8 +205,8 @@
return NULL; /* no error set, continue looking elsewhere */
PyErr_Format(PyExc_AttributeError,
- "cffi lib '%.200s' has no function,"
- " global variable or constant named '%.200s'",
+ "cffi library '%.200s' has no function, constant "
+ "or global variable named '%.200s'",
PyText_AS_UTF8(lib->l_libname), s);
return NULL;
}
@@ -435,16 +432,16 @@
PyObject *libname, *dict;
libname = PyText_FromString(module_name);
+ if (libname == NULL)
+ goto err1;
+
dict = PyDict_New();
- if (libname == NULL || dict == NULL) {
- Py_XDECREF(dict);
- Py_XDECREF(libname);
- return NULL;
- }
+ if (dict == NULL)
+ goto err2;
lib = PyObject_New(LibObject, &Lib_Type);
if (lib == NULL)
- return NULL;
+ goto err3;
lib->l_types_builder = &ffi->types_builder;
lib->l_dict = dict;
@@ -454,6 +451,14 @@
lib->l_ffi = ffi;
lib->l_libhandle = dlopen_libhandle;
return lib;
+
+ err3:
+ Py_DECREF(dict);
+ err2:
+ Py_DECREF(libname);
+ err1:
+ cdlopen_close_ignore_errors(dlopen_libhandle);
+ return NULL;
}
static PyObject *address_of_global_var(PyObject *args)
diff --git a/_cffi1/manual2.py b/_cffi1/manual2.py
new file mode 100644
--- /dev/null
+++ b/_cffi1/manual2.py
@@ -0,0 +1,19 @@
+import _cffi_backend
+
+ffi = _cffi_backend.FFI(b"manual2",
+ _version = 0x2600,
+ _types = b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x00\x09\x00\x00\x00\x0B',
+ _globals = (b'\x00\x00\x00#close',),
+ _struct_unions = ((b'\x00\x00\x00\x03\x00\x00\x00\x00point_s',b'\x00\x00\x01\x11x',b'\x00\x00\x01\x11y'),),
+ _enums = (b'\x00\x00\x00\x04\x00\x00\x00\x01myenum_e\x00AA,BB,CC',),
+ _typenames = (b'\x00\x00\x00\x01myint_t',),
+ _consts = {'AA':0,'BB':1,'CC':2},
+)
+
+
+
+# trying it out
+lib = ffi.dlopen(None)
+assert lib.BB == 1
+x = lib.close(-42)
+assert x == -1
diff --git a/_cffi1/realize_c_type.c b/_cffi1/realize_c_type.c
--- a/_cffi1/realize_c_type.c
+++ b/_cffi1/realize_c_type.c
@@ -4,6 +4,8 @@
PyObject *types_dict;
PyObject *included_ffis;
PyObject *known_constants;
+ PyObject *_keepalive1;
+ PyObject *_keepalive2;
} builder_c_t;
@@ -72,6 +74,8 @@
Py_XDECREF(builder->included_ffis);
Py_XDECREF(builder->types_dict);
Py_XDECREF(builder->known_constants);
+ Py_XDECREF(builder->_keepalive1);
+ Py_XDECREF(builder->_keepalive2);
}
static int init_builder_c(builder_c_t *builder,
@@ -89,6 +93,8 @@
builder->types_dict = ldict;
builder->included_ffis = NULL;
builder->known_constants = NULL;
+ builder->_keepalive1 = NULL;
+ builder->_keepalive2 = NULL;
return 0;
}
More information about the pypy-commit
mailing list