[pypy-commit] cffi cpy-extension: Char arguments.

arigo noreply at buildbot.pypy.org
Tue Jun 12 17:29:31 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: cpy-extension
Changeset: r293:4f6d840ef0e4
Date: 2012-06-12 17:28 +0200
http://bitbucket.org/cffi/cffi/changeset/4f6d840ef0e4/

Log:	Char arguments.

diff --git a/c/_ffi_backend.c b/c/_ffi_backend.c
--- a/c/_ffi_backend.c
+++ b/c/_ffi_backend.c
@@ -593,6 +593,21 @@
     return -1;
 }
 
+static int _convert_to_char(PyObject *init)
+{
+    if (PyString_Check(init) && PyString_GET_SIZE(init) == 1) {
+        return (unsigned char)(PyString_AS_STRING(init)[0]);
+    }
+    if (CData_Check(init) &&
+           (((CDataObject *)init)->c_type->ct_flags & CT_PRIMITIVE_CHAR)) {
+        return (unsigned char)(((CDataObject *)init)->c_data[0]);
+    }
+    PyErr_Format(PyExc_TypeError,
+                 "initializer for ctype 'char' must be a string of length 1, "
+                 "not %.200s", Py_TYPE(init)->tp_name);
+    return -1;
+}
+
 static int
 convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init)
 {
@@ -708,17 +723,11 @@
         return 0;
     }
     if (ct->ct_flags & CT_PRIMITIVE_CHAR) {
-        if (PyString_Check(init) && PyString_GET_SIZE(init) == 1) {
-            data[0] = PyString_AS_STRING(init)[0];
-            return 0;
-        }
-        if (CData_Check(init) &&
-               (((CDataObject *)init)->c_type->ct_flags & CT_PRIMITIVE_CHAR)) {
-            data[0] = ((CDataObject *)init)->c_data[0];
-            return 0;
-        }
-        expected = "string of length 1";
-        goto cannot_convert;
+        int res = _convert_to_char(init);
+        if (res < 0)
+            return -1;
+        data[0] = res;
+        return 0;
     }
     if (ct->ct_flags & CT_STRUCT) {
 
@@ -3293,6 +3302,11 @@
     return _my_PyLong_AsUnsignedLongLong(obj, 1);
 }
 
+static char _cffi_to_c_char(PyObject *obj)
+{
+    return (char)_convert_to_char(obj);
+}
+
 static void *cffi_exports[] = {
     _cffi_to_c_char_p,
     _cffi_to_c_signed_char,
@@ -3308,6 +3322,7 @@
 #endif
     _cffi_to_c_unsigned_long,
     _cffi_to_c_unsigned_long_long,
+    _cffi_to_c_char,
 };
 
 /************************************************************/
diff --git a/cffi/verifier.py b/cffi/verifier.py
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -76,9 +76,11 @@
             if tp.name in ('float', 'double'):
                 # float types
                 converter = 'PyFloat_AsDouble'
+            #
             elif tp.name == 'char':
                 # char
-                xxx
+                converter = '_cffi_to_c_char'
+            #
             else:
                 unsigned = tp.name.startswith('unsigned ')
                 size = self.ffi.sizeof(bt)
@@ -225,6 +227,10 @@
 #  define _cffi_from_c_long_long PyInt_FromLong
 #endif
 
+static PyObject *_cffi_from_c_char(char x) {
+    return PyString_FromStringAndSize(&x, 1);
+}
+
 #define _cffi_to_c_short PyInt_AsLong
 #define _cffi_to_c_int PyInt_AsLong
 #define _cffi_to_c_long PyInt_AsLong
@@ -250,6 +256,8 @@
                  ((unsigned long(*)(PyObject *))_cffi_exports[7])
 #define _cffi_to_c_unsigned_long_long                                    \
                  ((unsigned long long(*)(PyObject *))_cffi_exports[8])
+#define _cffi_to_c_char                                                  \
+                 ((char(*)(PyObject *))_cffi_exports[9])
 
 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
@@ -59,6 +59,13 @@
         assert lib.foo(ffi.cast(typename, 46)) == 47
         py.test.raises(TypeError, lib.foo, None)
 
+def test_char_type():
+    ffi = FFI()
+    ffi.cdef("char foo(char);")
+    lib = ffi.verify("char foo(char x) { return x+1; }")
+    assert lib.foo("A") == "B"
+    py.test.raises(TypeError, lib.foo, "bar")
+
 
 def test_verify_typedefs():
     py.test.skip("XXX?")


More information about the pypy-commit mailing list