[pypy-commit] cffi cffi-1.0: Reimplement verify() as a hack that updates the old ffi object with
arigo
noreply at buildbot.pypy.org
Thu Apr 16 09:36:46 CEST 2015
Author: Armin Rigo <arigo at 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;')
More information about the pypy-commit
mailing list