[pypy-commit] cffi default: Test and fix: passing structures to functions through ffi.verify()

arigo noreply at buildbot.pypy.org
Thu Jun 28 11:49:03 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r549:1139c2b9f312
Date: 2012-06-28 00:33 +0200
http://bitbucket.org/cffi/cffi/changeset/1139c2b9f312/

Log:	Test and fix: passing structures to functions through ffi.verify()

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -3571,6 +3571,7 @@
     save_errno,
     _cffi_from_c_char,
     convert_to_object,
+    convert_from_object,
 };
 
 /************************************************************/
diff --git a/cffi/verifier.py b/cffi/verifier.py
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -145,15 +145,14 @@
 
     # ----------
 
-    def convert_to_c(self, tp, fromvar, tovar, errcode, is_funcarg=False):
+    def convert_funcarg_to_c(self, tp, fromvar, tovar, errcode):
         extraarg = ''
         if isinstance(tp, model.PrimitiveType):
             converter = '_cffi_to_c_%s' % (tp.name.replace(' ', '_'),)
             errvalue = '-1'
         #
         elif isinstance(tp, model.PointerType):
-            if (is_funcarg and
-                    isinstance(tp.totype, model.PrimitiveType) and
+            if (isinstance(tp.totype, model.PrimitiveType) and
                     tp.totype.name == 'char'):
                 converter = '_cffi_to_c_char_p'
             else:
@@ -161,6 +160,13 @@
                 extraarg = ', _cffi_type(%d)' % self.gettypenum(tp)
             errvalue = 'NULL'
         #
+        elif isinstance(tp, model.StructType):
+            # a struct (not a struct pointer) as a function argument
+            self.prnt('  if (_cffi_to_c((char*)&%s, _cffi_type(%d), %s) < 0)'
+                      % (tovar, self.gettypenum(tp), fromvar))
+            self.prnt('    %s;' % errcode)
+            return
+        #
         else:
             raise NotImplementedError(tp)
         #
@@ -231,8 +237,8 @@
         prnt()
         #
         for i, type in enumerate(tp.args):
-            self.convert_to_c(type, 'arg%d' % i, 'x%d' % i, 'return NULL',
-                              is_funcarg=True)
+            self.convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i,
+                                      'return NULL')
             prnt()
         #
         prnt('  _cffi_restore_errno();')
@@ -606,7 +612,9 @@
     ((PyObject *(*)(char))_cffi_exports[15])
 #define _cffi_from_c_deref                                               \
     ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16])
-#define _CFFI_NUM_EXPORTS 17
+#define _cffi_to_c                                                       \
+    ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17])
+#define _CFFI_NUM_EXPORTS 18
 
 #if SIZEOF_LONG < SIZEOF_LONG_LONG
 #  define _cffi_to_c_long_long PyLong_AsLongLong
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -50,6 +50,12 @@
     lib = ffi.verify("#include <string.h>")
     assert lib.strlen("hi there!") == 9
 
+def test_strlen_array_of_char():
+    ffi = FFI()
+    ffi.cdef("int strlen(char[]);")
+    lib = ffi.verify("#include <string.h>")
+    assert lib.strlen("hello") == 5
+
 
 all_integer_types = ['short', 'int', 'long', 'long long',
                      'signed char', 'unsigned char',
@@ -537,3 +543,18 @@
     """)
     s = ffi.new("struct foo_s", ['B', 1])
     assert lib.foo(50, s[0]) == ord('A')
+
+def test_autofilled_struct_as_argument():
+    ffi = FFI()
+    ffi.cdef("struct foo_s { char a; int b; ...; }; int foo(struct foo_s);")
+    lib = ffi.verify("""
+        struct foo_s {
+            int pad1, b, pad2, pad3;
+            char a;
+        };
+        int foo(struct foo_s s) {
+            return s.a - s.b;
+        }
+    """)
+    s = ffi.new("struct foo_s", ['B', 1])
+    assert lib.foo(s[0]) == ord('A')


More information about the pypy-commit mailing list