Author: Armin Rigo <[email protected]>
Branch: cpy-extension
Changeset: r292:55e6cbe5871a
Date: 2012-06-12 17:17 +0200
http://bitbucket.org/cffi/cffi/changeset/55e6cbe5871a/

Log:    Phew. All integer types.

diff --git a/c/_ffi_backend.c b/c/_ffi_backend.c
--- a/c/_ffi_backend.c
+++ b/c/_ffi_backend.c
@@ -579,10 +579,23 @@
     return 0;
 }
 
+static int _convert_overflow(PyObject *init, const char *ct_name)
+{
+    PyObject *s;
+    if (PyErr_Occurred())   /* already an exception pending */
+        return -1;
+    s = PyObject_Str(init);
+    if (s == NULL)
+        return -1;
+    PyErr_Format(PyExc_OverflowError, "integer %s does not fit '%s'",
+                 PyString_AS_STRING(s), ct_name);
+    Py_DECREF(s);
+    return -1;
+}
+
 static int
 convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init)
 {
-    PyObject *s;
     const char *expected;
     char buf[sizeof(PY_LONG_LONG)];
 
@@ -773,13 +786,7 @@
     return -1;
 
  overflow:
-    s = PyObject_Str(init);
-    if (s == NULL)
-        return -1;
-    PyErr_Format(PyExc_OverflowError, "integer %s does not fit '%s'",
-                 PyString_AS_STRING(s), ct->ct_name);
-    Py_DECREF(s);
-    return -1;
+    return _convert_overflow(init, ct->ct_name);
 
  cannot_convert:
     if (CData_Check(init))
@@ -3256,8 +3263,51 @@
     return NULL;
 }
 
+#define _cffi_to_c_PRIMITIVE(TARGETNAME, TARGET)        \
+static TARGET _cffi_to_c_##TARGETNAME(PyObject *obj) {  \
+    long tmp = PyInt_AsLong(obj);                       \
+    if (tmp != (TARGET)tmp)                             \
+        return (TARGET)_convert_overflow(obj, #TARGET); \
+    return (TARGET)tmp;                                 \
+}
+
+_cffi_to_c_PRIMITIVE(signed_char,    signed char)
+_cffi_to_c_PRIMITIVE(unsigned_char,  unsigned char)
+_cffi_to_c_PRIMITIVE(short,          short)
+_cffi_to_c_PRIMITIVE(unsigned_short, unsigned short)
+#if SIZEOF_INT < SIZEOF_LONG
+_cffi_to_c_PRIMITIVE(int,            int)
+_cffi_to_c_PRIMITIVE(unsigned_int,   unsigned int)
+#endif
+
+static unsigned long _cffi_to_c_unsigned_long(PyObject *obj)
+{
+    unsigned PY_LONG_LONG value = _my_PyLong_AsUnsignedLongLong(obj, 1);
+    if (value != (unsigned long)value)
+        return (unsigned long)_convert_overflow(obj, "unsigned long");
+    return (unsigned long)value;
+}
+
+static unsigned PY_LONG_LONG _cffi_to_c_unsigned_long_long(PyObject *obj)
+{
+    return _my_PyLong_AsUnsignedLongLong(obj, 1);
+}
+
 static void *cffi_exports[] = {
     _cffi_to_c_char_p,
+    _cffi_to_c_signed_char,
+    _cffi_to_c_unsigned_char,
+    _cffi_to_c_short,
+    _cffi_to_c_unsigned_short,
+#if SIZEOF_INT < SIZEOF_LONG
+    _cffi_to_c_int,
+    _cffi_to_c_unsigned_int,
+#else
+    0,
+    0,
+#endif
+    _cffi_to_c_unsigned_long,
+    _cffi_to_c_unsigned_long_long,
 };
 
 /************************************************************/
diff --git a/cffi/verifier.py b/cffi/verifier.py
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -72,19 +72,36 @@
 
     def convert_to_c(self, tp, fromvar, tovar, errcode, is_funcarg=False):
         if isinstance(tp, model.PrimitiveType):
+            bt = self.ffi._get_cached_btype(tp)
             if tp.name in ('float', 'double'):
                 # float types
                 converter = 'PyFloat_AsDouble'
-                errvalue = '-1'
-            elif tp.name.startswith('unsigned '):
-                # unsigned integer types
-                xxx
             elif tp.name == 'char':
                 # char
                 xxx
             else:
-                # signed integer types
-                xxx
+                unsigned = tp.name.startswith('unsigned ')
+                size = self.ffi.sizeof(bt)
+                size_of_long = self.ffi.sizeof('long')
+                if size > size_of_long:
+                    # a 64-bit long long type on a 32-bit platform
+                    if unsigned:
+                        converter = '_cffi_to_c_unsigned_long_long'
+                    else:
+                        converter = 'PyLong_AsLongLong'
+                #
+                elif size == size_of_long and unsigned:
+                    # 'unsigned long' or an equivalently-sized unsigned type
+                    converter = '_cffi_to_c_unsigned_long'
+                #
+                elif size == size_of_long:
+                    # fits precisely in a 'long'
+                    converter = 'PyInt_AsLong'
+                else:
+                    # shorter than a 'long'
+                    converter = '_cffi_to_c_%s' % (tp.name.replace(' ', '_'),)
+            #
+            errvalue = '-1'
         #
         elif isinstance(tp, model.PointerType):
             if (is_funcarg and
@@ -209,16 +226,30 @@
 #endif
 
 #define _cffi_to_c_short PyInt_AsLong
-#define _cffi_to_c_short PyInt_AsLong
-#define _cffi_to_c_short PyInt_AsLong
-#define _cffi_to_c_short PyInt_AsLong
-#define _cffi_to_c_short PyInt_AsLong
-#define _cffi_to_c_short PyInt_AsLong
+#define _cffi_to_c_int PyInt_AsLong
+#define _cffi_to_c_long PyInt_AsLong
+
 #define _cffi_to_c_double PyFloat_AsDouble
 #define _cffi_to_c_float PyFloat_AsDouble
 
-#define _cffi_to_c_char_p ((char *(*)(PyObject *))_cffi_exports[0])
-
+#define _cffi_to_c_char_p                                                \
+                 ((char *(*)(PyObject *))_cffi_exports[0])
+#define _cffi_to_c_signed_char                                           \
+                 ((signed char(*)(PyObject *))_cffi_exports[1])
+#define _cffi_to_c_unsigned_char                                         \
+                 ((unsigned char(*)(PyObject *))_cffi_exports[2])
+#define _cffi_to_c_short                                                 \
+                 ((short(*)(PyObject *))_cffi_exports[3])
+#define _cffi_to_c_unsigned_short                                        \
+                 ((unsigned short(*)(PyObject *))_cffi_exports[4])
+#define _cffi_to_c_int                                                   \
+                 ((int(*)(PyObject *))_cffi_exports[5])
+#define _cffi_to_c_unsigned_int                                          \
+                 ((unsigned int(*)(PyObject *))_cffi_exports[6])
+#define _cffi_to_c_unsigned_long                                         \
+                 ((unsigned long(*)(PyObject *))_cffi_exports[7])
+#define _cffi_to_c_unsigned_long_long                                    \
+                 ((unsigned long long(*)(PyObject *))_cffi_exports[8])
 
 static void **_cffi_exports;
 
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -55,6 +55,9 @@
         ffi.cdef("%s foo(%s);" % (typename, typename))
         lib = ffi.verify("%s foo(%s x) { return x+1; }" % (typename, typename))
         assert lib.foo(42) == 43
+        assert lib.foo(44L) == 45
+        assert lib.foo(ffi.cast(typename, 46)) == 47
+        py.test.raises(TypeError, lib.foo, None)
 
 
 def test_verify_typedefs():
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to