Commits

Armin Rigo committed 68c0d7f

Ignore the declared type for global int constants.

  • Participants
  • Parent commits 0d40d81
  • Branches cpy-extension

Comments (0)

Files changed (3)

File cffi/model.py

     def get_c_name(self, replace_with=''):
         return self.name + replace_with
 
+    def is_char_type(self):
+        return self.name == 'char'
+    def is_signed_type(self):
+        return self.is_integer_type() and not self.is_unsigned_type()
+    def is_unsigned_type(self):
+        return self.name.startswith('unsigned ')
     def is_integer_type(self):
-        return not self.is_float_type()
-
+        return not self.is_float_type() and not self.is_char_type()
     def is_float_type(self):
         return self.name in ('double', 'float')
 

File cffi/verifier.py

     # constants, likely declared with '#define'
 
     def generate_cpy_constant_decl(self, tp, name):
+        is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
         prnt = self.prnt
         my_func_name = '_cffi_const_%s' % name
         prnt('static int %s(PyObject *dct)' % my_func_name)
         prnt('{')
-        prnt('  %s;' % tp.get_c_name(' i'))
+        if not is_int:
+            prnt('  %s;' % tp.get_c_name(' i'))
         prnt('  PyObject *o;')
         prnt('  int res;')
         if self.chained_list_constants is not None:
             prnt('  if (%s(dct) < 0)' % self.chained_list_constants)
             prnt('    return -1;')
         self.chained_list_constants = my_func_name
-        prnt('  i = (%s);' % (name,))
-        prnt('  o = %s;' % (self.convert_expr_from_c(tp, 'i'),))
+        if not is_int:
+            prnt('  i = (%s);' % (name,))
+            prnt('  o = %s;' % (self.convert_expr_from_c(tp, 'i'),))
+        else:
+            prnt('  if ((%s) == (long)(%s))' % (name, name))
+            prnt('    o = PyInt_FromLong((long)(%s));' % (name,))
+            prnt('  else if ((%s) == (long long)(%s))' % (name, name))
+            prnt('    o = PyLong_FromLongLong((long long)(%s));' % (name,))
+            prnt('  else')
+            prnt('    o = PyLong_FromUnsignedLongLong(%s);' % (name,))
         prnt('  if (o == NULL)')
         prnt('    return -1;')
         prnt('  res = PyDict_SetItemString(dct, "%s", o);' % name)

File testing/test_verify.py

 import py
 import math
-from cffi import FFI, VerificationError, VerificationMissing
+from cffi import FFI, VerificationError, VerificationMissing, model
 
 
 def test_missing_function():
                      'unsigned long', 'unsigned long long']
 all_signed_integer_types = [_typename for _typename in all_integer_types
                                       if not _typename.startswith('unsigned ')]
+all_unsigned_integer_types = [_typename for _typename in all_integer_types
+                                        if _typename.startswith('unsigned ')]
 all_float_types = ['float', 'double']
 
+def test_primitive_category():
+    for typename in all_integer_types + all_float_types + ['char']:
+        tp = model.PrimitiveType(typename)
+        assert tp.is_char_type() == (typename == 'char')
+        assert tp.is_signed_type() == (typename in all_signed_integer_types)
+        assert tp.is_unsigned_type()== (typename in all_unsigned_integer_types)
+        assert tp.is_integer_type() == (typename in all_integer_types)
+        assert tp.is_float_type() == (typename in all_float_types)
+
 def test_all_integer_and_float_types():
     for typename in all_integer_types + all_float_types:
         ffi = FFI()
     assert lib.AA == 42
     assert lib.BB == -43
     assert lib.CC == 44
+
+def test_global_const_int_size():
+    # integer constants: ignore the declared type, always just use the value
+    for value in [-2**80, -2**40, -2**20, -2**10, -2**5, -1,
+                  2**5, 2**10, 2**20, 2**40, 2**80]:
+        ffi = FFI()
+        if value == int(ffi.cast("long long", value)):
+            vstr = '%dLL' % value
+        elif value == int(ffi.cast("unsigned long long", value)):
+            vstr = '%dULL' % value
+        else:
+            continue
+        ffi.cdef("static const unsigned short AA;")
+        lib = ffi.verify("#define AA %s\n" % vstr)
+        assert lib.AA == value
+        assert type(lib.AA) is type(int(lib.AA))