Author: Armin Rigo <[email protected]>
Branch: cffi-1.0
Changeset: r1991:c7865fba2eeb
Date: 2015-05-12 14:11 +0200
http://bitbucket.org/cffi/cffi/changeset/c7865fba2eeb/
Log: Getting started on 'recompiler' producing a python file for dlopen()
diff --git a/cffi/cffi_opcode.py b/cffi/cffi_opcode.py
--- a/cffi/cffi_opcode.py
+++ b/cffi/cffi_opcode.py
@@ -1,14 +1,21 @@
+import struct
class CffiOp(object):
def __init__(self, op, arg):
self.op = op
self.arg = arg
+
def as_c_expr(self):
if self.op is None:
assert isinstance(self.arg, str)
return '(_cffi_opcode_t)(%s)' % (self.arg,)
classname = CLASS_NAME[self.op]
return '_CFFI_OP(_CFFI_OP_%s, %d)' % (classname, self.arg)
+
+ def as_bytes(self):
+ assert self.op is not None
+ return struct.pack(">i", (self.arg << 8) | self.op)
+
def __str__(self):
classname = CLASS_NAME.get(self.op, self.op)
return '(%s %s)' % (classname, self.arg)
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -6,6 +6,7 @@
class Recompiler:
def __init__(self, ffi, module_name):
+ assert isinstance(module_name, bytes)
self.ffi = ffi
self.module_name = module_name
@@ -118,7 +119,7 @@
g.close()
return lines
- def write_source_to_f(self, f, preamble):
+ def write_c_source_to_f(self, f, preamble):
self._f = f
prnt = self._prnt
#
@@ -264,6 +265,35 @@
prnt('#endif')
self.ffi._recompiler_module_name = self.module_name
+ def _to_py(self, x):
+ if isinstance(x, bytes):
+ r = repr(x)
+ if not r.startswith('b'):
+ r = 'b' + r
+ return r
+ raise TypeError(type(x).__name__)
+
+ def write_py_source_to_f(self, f):
+ self._f = f
+ prnt = self._prnt
+ #
+ # header
+ prnt("# auto-generated file")
+ prnt("import _cffi_backend")
+ prnt()
+ prnt("ffi = _cffi_backend.FFI(%s," % (self._to_py(self.module_name),))
+ #
+ # the '_types' keyword argument
+ self.cffi_types = tuple(self.cffi_types) # don't change any more
+ types_lst = [op.as_bytes() for op in self.cffi_types]
+ prnt(' _types = %s,' % (self._to_py(''.join(types_lst)),))
+ typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()])
+ #
+ #.......
+ #
+ # the footer
+ prnt(')')
+
# ----------
def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode):
@@ -897,22 +927,32 @@
s = s.encode('ascii')
super(NativeIO, self).write(s)
-def make_c_source(ffi, module_name, preamble, target_c_file):
+def _make_c_or_py_source(ffi, module_name, preamble, target_file):
recompiler = Recompiler(ffi, module_name)
recompiler.collect_type_table()
f = NativeIO()
- recompiler.write_source_to_f(f, preamble)
+ if preamble is not None:
+ recompiler.write_c_source_to_f(f, preamble)
+ else:
+ recompiler.write_py_source_to_f(f)
output = f.getvalue()
try:
- with open(target_c_file, 'r') as f1:
+ with open(target_file, 'r') as f1:
if f1.read(len(output) + 1) != output:
raise IOError
return False # already up-to-date
except IOError:
- with open(target_c_file, 'w') as f1:
+ with open(target_file, 'w') as f1:
f1.write(output)
return True
+def make_c_source(ffi, module_name, preamble, target_c_file):
+ assert preamble is not None
+ return _make_c_or_py_source(ffi, module_name, preamble, target_c_file)
+
+def make_py_source(ffi, module_name, target_py_file):
+ return _make_c_or_py_source(ffi, module_name, None, target_py_file)
+
def _get_extension(module_name, c_file, kwds):
source_name = ffiplatform.maybe_relative_path(c_file)
return ffiplatform.get_extension(source_name, module_name, **kwds)
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
@@ -1,57 +1,18 @@
import py
-py.test.skip("later")
+from cffi import FFI
+from cffi.recompiler import make_py_source
+from testing.udir import udir
-from cffi1 import FFI
-import math
+def test_simple():
+ ffi = FFI()
+ ffi.cdef("int close(int); static const int BB = 42;")
+ target = udir.join('test_simple.py')
+ assert make_py_source(ffi, 'test_simple', str(target))
+ assert target.read() == r"""# auto-generated file
+import _cffi_backend
-def test_cdef_struct():
- ffi = FFI()
- ffi.cdef("struct foo_s { int a, b; };")
- assert ffi.sizeof("struct foo_s") == 8
-
-def test_cdef_union():
- ffi = FFI()
- ffi.cdef("union foo_s { int a, b; };")
- assert ffi.sizeof("union foo_s") == 4
-
-def test_cdef_struct_union():
- ffi = FFI()
- ffi.cdef("union bar_s { int a; }; struct foo_s { int b; };")
- assert ffi.sizeof("union bar_s") == 4
- assert ffi.sizeof("struct foo_s") == 4
-
-def test_cdef_struct_typename_1():
- ffi = FFI()
- ffi.cdef("typedef struct { int a; } t1; typedef struct { t1* m; } t2;")
- assert ffi.sizeof("t2") == ffi.sizeof("void *")
- assert ffi.sizeof("t1") == 4
-
-def test_cdef_struct_typename_2():
- ffi = FFI()
- ffi.cdef("typedef struct { int a; } *p1; typedef struct { p1 m; } *p2;")
- p2 = ffi.new("p2")
- assert ffi.sizeof(p2[0]) == ffi.sizeof("void *")
- assert ffi.sizeof(p2[0].m) == ffi.sizeof("void *")
-
-def test_cdef_struct_anon_1():
- ffi = FFI()
- ffi.cdef("typedef struct { int a; } t1; struct foo_s { t1* m; };")
- assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *")
-
-def test_cdef_struct_anon_2():
- ffi = FFI()
- ffi.cdef("typedef struct { int a; } *p1; struct foo_s { p1 m; };")
- assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *")
-
-def test_cdef_struct_anon_3():
- ffi = FFI()
- ffi.cdef("typedef struct { int a; } **pp; struct foo_s { pp m; };")
- assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *")
-
-def test_math_sin():
- ffi = FFI()
- ffi.cdef("double sin(double);")
- m = ffi.dlopen('m')
- x = m.sin(1.23)
- assert x == math.sin(1.23)
+ffi = _cffi_backend.FFI(b'test_simple',
+ _types = b'\x00\x00\x01\r\x00\x00\x07\x01\x00\x00\x00\x0f',
+)
+"""
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit