Author: Armin Rigo <ar...@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; } _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit