Author: Armin Rigo <ar...@tunes.org> Branch: cffi-1.0 Changeset: r1722:3758e99173fd Date: 2015-04-16 09:17 +0200 http://bitbucket.org/cffi/cffi/changeset/3758e99173fd/
Log: Reimplement verify() as a hack that updates the old ffi object with the ffi object from the extension module. diff --git a/new/cffi1_module.c b/new/cffi1_module.c --- a/new/cffi1_module.c +++ b/new/cffi1_module.c @@ -49,7 +49,7 @@ if (m == NULL) return -1; - FFIObject *ffi = ffi_internal_new(NULL, ctx); + FFIObject *ffi = ffi_internal_new(&FFI_Type, ctx, 1); Py_XINCREF(ffi); /* make the ffi object really immortal */ if (ffi == NULL || PyModule_AddObject(m, "ffi", (PyObject *)ffi) < 0) return -1; diff --git a/new/ffi_obj.c b/new/ffi_obj.c --- a/new/ffi_obj.c +++ b/new/ffi_obj.c @@ -23,19 +23,21 @@ PyObject *types_dict; PyObject *gc_wrefs; struct _cffi_parse_info_s info; + int ctx_is_static; _cffi_opcode_t internal_output[FFI_COMPLEXITY_OUTPUT]; }; static FFIObject *ffi_internal_new(PyTypeObject *ffitype, - const struct _cffi_type_context_s *ctx) + const struct _cffi_type_context_s *ctx, + int ctx_is_static) { PyObject *dict = PyDict_New(); if (dict == NULL) return NULL; FFIObject *ffi; - if (ffitype == NULL) { - ffi = (FFIObject *)PyObject_New(FFIObject, &FFI_Type); + if (ctx_is_static) { + ffi = (FFIObject *)PyObject_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 */ } @@ -51,6 +53,7 @@ ffi->info.ctx = ctx; ffi->info.output = ffi->internal_output; ffi->info.output_size = FFI_COMPLEXITY_OUTPUT; + ffi->ctx_is_static = ctx_is_static; return ffi; } @@ -60,7 +63,7 @@ Py_DECREF(ffi->types_dict); Py_XDECREF(ffi->gc_wrefs); - { + if (!ffi->ctx_is_static) { const void *mem[] = {ffi->info.ctx->types, ffi->info.ctx->globals, ffi->info.ctx->constants, @@ -98,7 +101,7 @@ } memset(ctx, 0, sizeof(struct _cffi_type_context_s)); - result = (PyObject *)ffi_internal_new(type, ctx); + result = (PyObject *)ffi_internal_new(type, ctx, 0); if (result == NULL) { PyMem_Free(ctx); return NULL; @@ -516,7 +519,40 @@ } #endif +static PyObject *ffi__verified(FFIObject *self, PyObject *args) +{ + FFIObject *srcffi; + + if (!PyArg_ParseTuple(args, "O!:_verified", &FFI_Type, &srcffi)) + return NULL; + + if (!srcffi->ctx_is_static) + goto invalid; + + if (self->ctx_is_static) + goto invalid; + + size_t i; + const char *p = (const char *)self->info.ctx; + for (i = 0; i < sizeof(struct _cffi_type_context_s); i++) { + if (*p++ != '\0') + goto invalid; + } + + PyMem_Free((void *)self->info.ctx); + self->ctx_is_static = 1; + self->info.ctx = srcffi->info.ctx; + + Py_INCREF(Py_None); + return Py_None; + + invalid: + PyErr_SetString(PyExc_ValueError, "XXX invalid source or destination"); + return NULL; +} + static PyMethodDef ffi_methods[] = { + {"_verified", (PyCFunction)ffi__verified, METH_VARARGS}, #if 0 {"addressof", (PyCFunction)ffi_addressof, METH_VARARGS}, {"cast", (PyCFunction)ffi_cast, METH_VARARGS}, diff --git a/new/recompiler.py b/new/recompiler.py --- a/new/recompiler.py +++ b/new/recompiler.py @@ -125,7 +125,7 @@ nums[step_name] = len(lst) if nums[step_name] > 0: lst.sort() # sort by name, which is at the start of each line - prnt('static const struct _cffi_%s_s _cffi_%s[] = {' % ( + prnt('static const struct _cffi_%s_s _cffi_%ss[] = {' % ( step_name, step_name)) for line in lst: prnt(line) @@ -408,10 +408,32 @@ self.cffi_types[index] = CffiOp(OP_ARRAY, item_index) self.cffi_types[index + 1] = CffiOp(None, '%d' % (tp.length,)) -def make_c_source(ffi, target_c_file, preamble): - module_name, ext = os.path.splitext(os.path.basename(target_c_file)) - assert ext, "no extension!" +def make_c_source(ffi, module_name, preamble, target_c_file): recompiler = Recompiler(ffi, module_name) recompiler.collect_type_table() with open(target_c_file, 'w') as f: recompiler.write_source_to_f(f, preamble) + +def _get_extension(module_name, c_file, kwds): + source_name = ffiplatform.maybe_relative_path(c_file) + include_dirs = kwds.setdefault('include_dirs', []) + include_dirs.insert(0, '.') # XXX + return ffiplatform.get_extension(source_name, module_name, **kwds) + +def recompile(ffi, module_name, preamble, tmpdir=None, **kwds): + if tmpdir is None: + tmpdir = 'build' + if not os.path.isdir(tmpdir): + os.mkdir(tmpdir) + c_file = os.path.join(tmpdir, module_name + '.c') + ext = _get_extension(module_name, c_file, kwds) + make_c_source(ffi, module_name, preamble, c_file) + outputfilename = ffiplatform.compile(tmpdir, ext) + return outputfilename + +def verify(ffi, module_name, preamble, *args, **kwds): + import imp + outputfilename = recompile(ffi, module_name, preamble, *args, **kwds) + module = imp.load_dynamic(module_name, outputfilename) + ffi._verified(module.ffi) + return module.lib diff --git a/new/test_recompiler.py b/new/test_recompiler.py --- a/new/test_recompiler.py +++ b/new/test_recompiler.py @@ -1,6 +1,5 @@ -from recompiler import Recompiler, make_c_source +from recompiler import Recompiler, verify from cffi1 import FFI -from udir import udir def check_type_table(input, expected_output): @@ -62,16 +61,21 @@ def test_math_sin(): + import math ffi = FFI() ffi.cdef("float sin(double); double cos(double);") - make_c_source(ffi, str(udir.join('math_sin.c')), '#include <math.h>') + lib = verify(ffi, 'test_math_sin', '#include <math.h>') + assert lib.cos(1.43) == math.cos(1.43) def test_global_var_array(): ffi = FFI() ffi.cdef("int a[100];") - make_c_source(ffi, str(udir.join('global_var_array.c')), 'int a[100];') + lib = verify(ffi, 'test_global_var_array', 'int a[100] = { 9999 };') + #lib.a[42] = 123456 + #assert lib.a[42] == 123456 + #assert lib.a[0] == 9999 def test_typedef(): ffi = FFI() ffi.cdef("typedef int **foo_t;") - make_c_source(ffi, str(udir.join('typedef.c')), 'typedef int **foo_t;') + lib = verify(ffi, 'test_typedef', 'typedef int **foo_t;') _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit