[pypy-commit] cffi default: Tests and fixes that include directly using a file as "FILE *".

arigo noreply at buildbot.pypy.org
Fri Oct 26 10:03:12 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r1008:fa7aacc08b34
Date: 2012-10-26 10:03 +0200
http://bitbucket.org/cffi/cffi/changeset/fa7aacc08b34/

Log:	Tests and fixes that include directly using a file as "FILE *".

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -87,6 +87,7 @@
 #define CT_CUSTOM_FIELD_POS     32768
 #define CT_IS_LONGDOUBLE        65536
 #define CT_IS_BOOL             131072
+#define CT_IS_FILE             262144
 #define CT_PRIMITIVE_ANY  (CT_PRIMITIVE_SIGNED |        \
                            CT_PRIMITIVE_UNSIGNED |      \
                            CT_PRIMITIVE_CHAR |          \
@@ -942,6 +943,11 @@
         CTypeDescrObject *ctinit;
 
         if (!CData_Check(init)) {
+            if (PyFile_Check(init) &&
+                (ct->ct_itemdescr->ct_flags & CT_IS_FILE)) {
+                *(FILE **)data = PyFile_AsFile(init);
+                return 0;
+            }
             expected = "cdata pointer";
             goto cannot_convert;
         }
@@ -1726,9 +1732,8 @@
         /* from a unicode, we add the null terminator */
         length = _my_PyUnicode_SizeAsWideChar(init) + 1;
     }
-    else if (PyFile_Check(init)) {
-        if (strcmp(ctptr->ct_itemdescr->ct_name, "struct _IO_FILE") != 0)
-            return 0;
+    else if (PyFile_Check(init) &&
+             (ctptr->ct_itemdescr->ct_flags & CT_IS_FILE)) {
         output_data[0] = (char *)PyFile_AsFile(init);
         return 1;
     }
@@ -3028,9 +3033,14 @@
 static PyObject *b_new_struct_type(PyObject *self, PyObject *args)
 {
     char *name;
+    int flag;
     if (!PyArg_ParseTuple(args, "s:new_struct_type", &name))
         return NULL;
-    return _b_struct_or_union_type("struct", name, CT_STRUCT);
+
+    flag = CT_STRUCT;
+    if (strcmp(name, "_IO_FILE") == 0)
+        flag |= CT_IS_FILE;
+    return _b_struct_or_union_type("struct", name, flag);
 }
 
 static PyObject *b_new_union_type(PyObject *self, PyObject *args)
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -1222,3 +1222,56 @@
     assert ffi_r() is not None
     assert lib_r() is not None
     assert func() == 42
+
+def test_FILE_stored_in_stdout():
+    ffi = FFI()
+    ffi.cdef("int printf(const char *, ...); FILE *setstdout(FILE *);")
+    lib = ffi.verify("""
+        #include <stdio.h>
+        FILE *setstdout(FILE *f) {
+            FILE *result = stdout;
+            stdout = f;
+            return result;
+        }
+    """)
+    import posix
+    fdr, fdw = posix.pipe()
+    fw1 = posix.fdopen(fdw, 'wb', 256)
+    old_stdout = lib.setstdout(fw1)
+    try:
+        #
+        fw1.write(b"X")
+        r = lib.printf(b"hello, %d!\n", ffi.cast("int", 42))
+        fw1.close()
+        assert r == len("hello, 42!\n")
+        #
+    finally:
+        lib.setstdout(old_stdout)
+    #
+    result = posix.read(fdr, 256)
+    posix.close(fdr)
+    assert result == b"Xhello, 42!\n"
+
+def test_FILE_stored_explicitly():
+    ffi = FFI()
+    ffi.cdef("int myprintf(const char *, int); FILE *myfile;")
+    lib = ffi.verify("""
+        #include <stdio.h>
+        FILE *myfile;
+        int myprintf(const char *out, int value) {
+            return fprintf(myfile, out, value);
+        }
+    """)
+    import posix
+    fdr, fdw = posix.pipe()
+    fw1 = posix.fdopen(fdw, 'wb', 256)
+    lib.myfile = fw1
+    #
+    fw1.write(b"X")
+    r = lib.myprintf(b"hello, %d!\n", ffi.cast("int", 42))
+    fw1.close()
+    assert r == len("hello, 42!\n")
+    #
+    result = posix.read(fdr, 256)
+    posix.close(fdr)
+    assert result == b"Xhello, 42!\n"


More information about the pypy-commit mailing list