[pypy-commit] pypy default: Passing file arguments.

arigo noreply at buildbot.pypy.org
Sat Oct 20 10:21:47 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r58268:235d902b48ba
Date: 2012-10-20 10:21 +0200
http://bitbucket.org/pypy/pypy/changeset/235d902b48ba/

Log:	Passing file arguments.

diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -147,9 +147,13 @@
                 argtype = self.fargs[i]
                 if isinstance(argtype, W_CTypePointer):
                     data = rffi.ptradd(buffer, cif_descr.exchange_args[i])
-                    if get_mustfree_flag(data):
+                    flag = get_mustfree_flag(data)
+                    if flag == 1:
                         raw_string = rffi.cast(rffi.CCHARPP, data)[0]
                         lltype.free(raw_string, flavor='raw')
+                    elif flag == 2:
+                        file = rffi.cast(rffi.CCHARPP, data)[0]
+                        rffi_fclose(file)
             lltype.free(buffer, flavor='raw')
         return w_res
 
@@ -164,6 +168,26 @@
     assert isinstance(abi, int)
     return space.wrap(abi)
 
+rffi_fdopen = rffi.llexternal("fdopen", [rffi.INT, rffi.CCHARP], rffi.CCHARP)
+rffi_fclose = rffi.llexternal("fclose", [rffi.CCHARP], rffi.INT)
+
+def prepare_file_call_argument(fileobj):
+    import os
+    space = fileobj.space
+    fd = fileobj.direct_fileno()
+    if fd < 0:
+        raise OperationError(self.space.w_ValueError,
+                             self.space.wrap("file has no OS file descriptor"))
+    try:
+        fd2 = os.dup(fd)
+        f = rffi_fdopen(fd2, fileobj.mode)
+        if not f:
+            os.close(fd2)
+            raise OSError(rposix.get_errno(), "fdopen failed")
+    except OSError, e:
+        raise wrap_oserror(space, e)
+    return f
+
 # ____________________________________________________________
 
 
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -177,7 +177,8 @@
 
 
 class W_CTypePointer(W_CTypePtrBase):
-    _attrs_ = []
+    _attrs_ = ['is_file']
+    _immutable_fields_ = ['is_file']
 
     def __init__(self, space, ctitem):
         from pypy.module._cffi_backend import ctypearray
@@ -186,6 +187,7 @@
             extra = "(*)"    # obscure case: see test_array_add
         else:
             extra = " *"
+        self.is_file = (ctitem.name == "struct _IO_FILE")
         W_CTypePtrBase.__init__(self, space, size, extra, 2, ctitem)
 
     def newp(self, w_init):
@@ -234,7 +236,7 @@
         p = rffi.ptradd(cdata, i * self.ctitem.size)
         return cdataobj.W_CData(space, p, self)
 
-    def _prepare_pointer_call_argument(self, w_init):
+    def _prepare_pointer_call_argument(self, w_init, cdata):
         space = self.space
         if (space.isinstance_w(w_init, space.w_list) or
             space.isinstance_w(w_init, space.w_tuple)):
@@ -242,10 +244,19 @@
         elif space.isinstance_w(w_init, space.w_basestring):
             # from a string, we add the null terminator
             length = space.int_w(space.len(w_init)) + 1
+        elif self.is_file:
+            from pypy.module._file.interp_file import W_File
+            from pypy.module._cffi_backend import ctypefunc
+            ob = space.interpclass_w(w_init)
+            if isinstance(ob, W_File):
+                result = ctypefunc.prepare_file_call_argument(ob)
+                rffi.cast(rffi.CCHARPP, cdata)[0] = result
+                return 2
+            return 0
         else:
-            return lltype.nullptr(rffi.CCHARP.TO)
+            return 0
         if self.ctitem.size <= 0:
-            return lltype.nullptr(rffi.CCHARP.TO)
+            return 0
         try:
             datasize = ovfcheck(length * self.ctitem.size)
         except OverflowError:
@@ -258,25 +269,19 @@
         except Exception:
             lltype.free(result, flavor='raw')
             raise
-        return result
+        rffi.cast(rffi.CCHARPP, cdata)[0] = result
+        return 1
 
     def convert_argument_from_object(self, cdata, w_ob):
         from pypy.module._cffi_backend.ctypefunc import set_mustfree_flag
         space = self.space
         ob = space.interpclass_w(w_ob)
-        if isinstance(ob, cdataobj.W_CData):
-            buffer = lltype.nullptr(rffi.CCHARP.TO)
-        else:
-            buffer = self._prepare_pointer_call_argument(w_ob)
-        #
-        if buffer:
-            rffi.cast(rffi.CCHARPP, cdata)[0] = buffer
-            set_mustfree_flag(cdata, True)
-            return True
-        else:
-            set_mustfree_flag(cdata, False)
+        result = (not isinstance(ob, cdataobj.W_CData) and
+                  self._prepare_pointer_call_argument(w_ob, cdata))
+        if result == 0:
             self.convert_from_object(cdata, w_ob)
-            return False
+        set_mustfree_flag(cdata, result)
+        return result
 
     def getcfield(self, attr):
         return self.ctitem.getcfield(attr)


More information about the pypy-commit mailing list