[pypy-commit] cffi cffi-1.0: Includes of dlopen-style ffis. Negative constants in "static const int = ...".
arigo
noreply at buildbot.pypy.org
Sat May 16 10:58:56 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r2006:f28455444b8f
Date: 2015-05-16 10:59 +0200
http://bitbucket.org/cffi/cffi/changeset/f28455444b8f/
Log: Includes of dlopen-style ffis. Negative constants in "static const
int = ...".
diff --git a/c/cdlopen.c b/c/cdlopen.c
--- a/c/cdlopen.c
+++ b/c/cdlopen.c
@@ -134,19 +134,21 @@
FFIObject *ffi;
static char *keywords[] = {"module_name", "_version", "_types",
"_globals", "_struct_unions", "_enums",
- "_typenames", NULL};
+ "_typenames", "_includes", 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;
+ PyObject *typenames = NULL, *includes = NULL;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sns#O!O!O!O!:FFI", keywords,
+ if (!PyArg_ParseTupleAndKeywords(args, kwds,
+ "|sns#O!O!O!O!O!:FFI", keywords,
&ffiname, &version, &types, &types_len,
&PyTuple_Type, &globals,
&PyTuple_Type, &struct_unions,
&PyTuple_Type, &enums,
- &PyTuple_Type, &typenames))
+ &PyTuple_Type, &typenames,
+ &PyTuple_Type, &includes))
return -1;
ffi = (FFIObject *)self;
@@ -337,6 +339,18 @@
building = NULL;
}
+ if (includes != NULL) {
+ PyObject *included_libs;
+
+ included_libs = PyTuple_New(PyTuple_GET_SIZE(includes));
+ if (included_libs == NULL)
+ return -1;
+
+ Py_INCREF(includes);
+ ffi->types_builder.included_ffis = includes;
+ ffi->types_builder.included_libs = included_libs;
+ }
+
/* 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. */
diff --git a/cffi/cparser.py b/cffi/cparser.py
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -271,10 +271,19 @@
tp = self._get_type_pointer(tp)
self._declare('function ' + decl.name, tp)
elif (isinstance(tp, model.PrimitiveType) and
- tp.is_integer_type() and
- hasattr(decl, 'init') and hasattr(decl.init, 'value')
- and _r_int_literal.match(decl.init.value)):
+ tp.is_integer_type() and
+ hasattr(decl, 'init') and
+ hasattr(decl.init, 'value') and
+ _r_int_literal.match(decl.init.value)):
self._add_integer_constant(decl.name, decl.init.value)
+ elif (isinstance(tp, model.PrimitiveType) and
+ tp.is_integer_type() and
+ isinstance(decl.init, pycparser.c_ast.UnaryOp) and
+ decl.init.op == '-' and
+ hasattr(decl.init.expr, 'value') and
+ _r_int_literal.match(decl.init.expr.value)):
+ self._add_integer_constant(decl.name,
+ '-' + decl.init.expr.value)
elif self._is_constant_globalvar(node):
self._declare('constant ' + decl.name, tp)
else:
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -335,7 +335,7 @@
if not hasattr(ffi_to_include, '_recompiler_module_name'):
raise ffiplatform.VerificationError(
"this ffi includes %r, but the latter has not been "
- "turned into a C module" % (ffi_to_include,))
+ "compiled yet" % (ffi_to_include,))
prnt(' "%s",' % (ffi_to_include._recompiler_module_name,))
prnt(' NULL')
prnt('};')
@@ -417,6 +417,17 @@
# header
prnt("# auto-generated file")
prnt("import _cffi_backend")
+ #
+ # the 'import' of the included ffis
+ num_includes = len(self.ffi._included_ffis or ())
+ for i in range(num_includes):
+ ffi_to_include = self.ffi._included_ffis[i]
+ if not hasattr(ffi_to_include, '_recompiler_module_name'):
+ raise ffiplatform.VerificationError(
+ "this ffi includes %r, but the latter has not been "
+ "compiled yet" % (ffi_to_include,))
+ prnt('from %s import ffi as _ffi%d' % (
+ ffi_to_include._recompiler_module_name, i))
prnt()
prnt("ffi = _cffi_backend.FFI(%s," % (self._to_py(self.module_name),))
#
@@ -426,13 +437,20 @@
prnt(' _types = %s,' % (self._to_py(''.join(types_lst)),))
typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()])
#
+ # the keyword arguments from ALL_STEPS
for step_name in self.ALL_STEPS:
lst = self._lsts[step_name]
if len(lst) > 0 and step_name != "field":
prnt(' _%ss = %s,' % (step_name, self._to_py(lst)))
#
+ # the '_includes' keyword argument
+ if num_includes > 0:
+ prnt(' _includes = (%s,),' % (
+ ', '.join(['_ffi%d' % i for i in range(num_includes)]),))
+ #
# the footer
prnt(')')
+ self.ffi._recompiler_module_name = self.module_name
# ----------
diff --git a/testing/cffi1/test_dlopen.py b/testing/cffi1/test_dlopen.py
--- a/testing/cffi1/test_dlopen.py
+++ b/testing/cffi1/test_dlopen.py
@@ -82,3 +82,45 @@
_struct_unions = ((b'\x00\x00\x00\x03\x00\x00\x00\x10bar_s',),(b'\x00\x00\x00\x04\x00\x00\x00\x02foo_s',b'\x00\x00\x00\x11a',b'\x00\x00\x02\x11b')),
)
"""
+
+def test_include():
+ ffi = FFI()
+ ffi.cdef("#define ABC 123")
+ target = udir.join('test_include.py')
+ assert make_py_source(ffi, 'test_include', str(target))
+ assert target.read() == r"""# auto-generated file
+import _cffi_backend
+
+ffi = _cffi_backend.FFI(b'test_include',
+ _types = b'',
+ _globals = (b'\xFF\xFF\xFF\x1FABC',123,),
+)
+"""
+ #
+ ffi2 = FFI()
+ ffi2.include(ffi)
+ target2 = udir.join('test2_include.py')
+ assert make_py_source(ffi2, 'test2_include', str(target2))
+ assert target2.read() == r"""# auto-generated file
+import _cffi_backend
+from test_include import ffi as _ffi0
+
+ffi = _cffi_backend.FFI(b'test2_include',
+ _types = b'',
+ _includes = (_ffi0,),
+)
+"""
+
+def test_negative_constant():
+ ffi = FFI()
+ ffi.cdef("static const int BB = -42;")
+ target = udir.join('test_negative_constant.py')
+ assert make_py_source(ffi, 'test_negative_constant', str(target))
+ assert target.read() == r"""# auto-generated file
+import _cffi_backend
+
+ffi = _cffi_backend.FFI(b'test_negative_constant',
+ _types = b'',
+ _globals = (b'\xFF\xFF\xFF\x1FBB',-42,),
+)
+"""
diff --git a/testing/cffi1/test_re_python.py b/testing/cffi1/test_re_python.py
--- a/testing/cffi1/test_re_python.py
+++ b/testing/cffi1/test_re_python.py
@@ -8,6 +8,7 @@
def setup_module(mod):
SRC = """
#define FOOBAR (-42)
+ static const int FOOBAZ = -43;
int add42(int x) { return x + 42; }
struct foo_s;
typedef struct bar_s { int x; signed char a[]; } bar_t;
@@ -20,10 +21,12 @@
ext = ffiplatform.get_extension(str(c_file), '_test_re_python')
outputfilename = ffiplatform.compile(str(tmpdir), ext)
mod.extmod = outputfilename
+ mod.tmpdir = tmpdir
#
ffi = FFI()
ffi.cdef("""
#define FOOBAR -42
+ static const int FOOBAZ = -43;
int add42(int);
struct foo_s;
typedef struct bar_s { int x; signed char a[]; } bar_t;
@@ -31,6 +34,7 @@
""")
ffi.set_source('re_python_pysrc', None)
ffi.emit_python_code(str(tmpdir.join('re_python_pysrc.py')))
+ mod.original_ffi = ffi
#
sys.path.insert(0, str(tmpdir))
@@ -38,6 +42,7 @@
def test_constant():
from re_python_pysrc import ffi
assert ffi.integer_const('FOOBAR') == -42
+ assert ffi.integer_const('FOOBAZ') == -43
def test_function():
from re_python_pysrc import ffi
@@ -48,6 +53,7 @@
from re_python_pysrc import ffi
lib = ffi.dlopen(extmod)
assert lib.FOOBAR == -42
+ assert lib.FOOBAZ == -43
def test_opaque_struct():
from re_python_pysrc import ffi
@@ -67,3 +73,21 @@
assert ffi.integer_const("BB") == 1
e = ffi.cast("enum foo_e", 2)
assert ffi.string(e) == "CC"
+
+def test_include_1():
+ ffi2 = FFI()
+ ffi2.cdef("static const int k2 = 121212;")
+ ffi2.include(original_ffi)
+ assert 'macro FOOBAR' in original_ffi._parser._declarations
+ assert 'macro FOOBAZ' in original_ffi._parser._declarations
+ ffi2.set_source('re_python_pysrc', None)
+ ffi2.emit_python_code(str(tmpdir.join('_re_include_1.py')))
+ #
+ from _re_include_1 import ffi
+ assert ffi.integer_const('FOOBAR') == -42
+ assert ffi.integer_const('FOOBAZ') == -43
+ assert ffi.integer_const('k2') == 121212
+ lib = ffi.dlopen(None)
+ assert lib.FOOBAR == -42
+ assert lib.FOOBAZ == -43
+ assert lib.k2 == 121212
More information about the pypy-commit
mailing list