[pypy-commit] cffi cffi-1.0: enum

arigo noreply at buildbot.pypy.org
Tue May 12 17:02:31 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1998:e72977e45c75
Date: 2015-05-12 17:03 +0200
http://bitbucket.org/cffi/cffi/changeset/e72977e45c75/

Log:	enum

diff --git a/cffi/recompiler.py b/cffi/recompiler.py
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -2,6 +2,11 @@
 from cffi import ffiplatform, model
 from .cffi_opcode import *
 
+try:
+    int_type = (int, long)
+except NameError:    # Python 3
+    int_type = int
+
 
 class GlobalExpr:
     def __init__(self, name, address, type_op, size=0, check_value=None):
@@ -16,7 +21,7 @@
             self.name, self.address, self.type_op.as_c_expr(), self.size)
 
     def as_python_expr(self):
-        if self.check_value is None:
+        if not isinstance(self.check_value, int_type):
             raise ffiplatform.VerificationError(
                 "ffi.dlopen() will not be able to figure out the value of "
                 "constant %r (only integer constants are supported, and only "
@@ -35,6 +40,30 @@
     def as_python_expr(self):
         return "b'%s%s'" % (format_four_bytes(self.type_index), self.name)
 
+class EnumExpr:
+    def __init__(self, name, type_index, size, signed, allenums):
+        self.name = name
+        self.type_index = type_index
+        self.size = size
+        self.signed = signed
+        self.allenums = allenums
+
+    def as_c_expr(self):
+        return ('  { "%s", %d, _cffi_prim_int(%s, %s),\n'
+                '    "%s" },' % (self.name, self.type_index,
+                                 self.size, self.signed, self.allenums))
+
+    def as_python_expr(self):
+        prim_index = {
+            (1, 0): PRIM_UINT8,  (1, 1):  PRIM_INT8,
+            (2, 0): PRIM_UINT16, (2, 1):  PRIM_INT16,
+            (4, 0): PRIM_UINT32, (4, 1):  PRIM_INT32,
+            (8, 0): PRIM_UINT64, (8, 1):  PRIM_INT64,
+            }[self.size, self.signed]
+        return "b'%s%s%s\\x00%s'" % (format_four_bytes(self.type_index),
+                                     format_four_bytes(prim_index),
+                                     self.name, self.allenums)
+
 
 class Recompiler:
 
@@ -167,7 +196,7 @@
         lst = self._lsts["enum"]
         for tp, i in self._enums.items():
             assert i < len(lst)
-            assert lst[i].startswith('  { "%s"' % tp.name)
+            assert lst[i].name == tp.name
         assert len(lst) == len(self._enums)
 
     # ----------
@@ -855,11 +884,12 @@
     def _enum_ctx(self, tp, cname):
         type_index = self._typesdict[tp]
         type_op = CffiOp(OP_ENUM, -1)
-        for enumerator in tp.enumerators:
+        for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
             self._lsts["global"].append(
-                GlobalExpr(enumerator, '_cffi_const_%s' % enumerator, type_op))
+                GlobalExpr(enumerator, '_cffi_const_%s' % enumerator, type_op,
+                           check_value=enumvalue))
         #
-        if cname is not None and '$' not in cname:
+        if cname is not None and '$' not in cname and not self.target_is_python:
             size = "sizeof(%s)" % cname
             signed = "((%s)-1) <= 0" % cname
         else:
@@ -868,8 +898,7 @@
             signed = int(int(self.ffi.cast(basetp, -1)) < 0)
         allenums = ",".join(tp.enumerators)
         self._lsts["enum"].append(
-            '  { "%s", %d, _cffi_prim_int(%s, %s),\n'
-            '    "%s" },' % (tp.name, type_index, size, signed, allenums))
+            EnumExpr(tp.name, type_index, size, signed, allenums))
 
     def _generate_cpy_enum_ctx(self, tp, name):
         self._enum_ctx(tp, tp._get_c_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
@@ -53,3 +53,18 @@
     _typenames = (b'\x00\x00\x00\x00foobar_t',),
 )
 """
+
+def test_enum():
+    ffi = FFI()
+    ffi.cdef("enum myenum_e { AA, BB, CC=-42 };")
+    target = udir.join('test_enum.py')
+    assert make_py_source(ffi, 'test_enum', str(target))
+    assert target.read() == r"""# auto-generated file
+import _cffi_backend
+
+ffi = _cffi_backend.FFI(b'test_enum',
+    _types = b'\x00\x00\x00\x0B',
+    _globals = (b'\xFF\xFF\xFF\x0BAA',0,b'\xFF\xFF\xFF\x0BBB',1,b'\xFF\xFF\xFF\x0BCC',-42),
+    _enums = (b'\x00\x00\x00\x00\x00\x00\x00\x15myenum_e\x00AA,BB,CC',),
+)
+"""


More information about the pypy-commit mailing list