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