[pypy-svn] pypy jitypes2: support struct by value as return type

antocuni commits-noreply at bitbucket.org
Thu Dec 23 17:34:55 CET 2010


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: jitypes2
Changeset: r40212:1e6f3d9f7e72
Date: 2010-12-23 17:26 +0100
http://bitbucket.org/pypy/pypy/changeset/1e6f3d9f7e72/

Log:	support struct by value as return type

diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -406,7 +406,13 @@
                             rffi.cast(rffi.VOIDPP, ll_args))
         if RESULT is not lltype.Void:
             TP = lltype.Ptr(rffi.CArray(RESULT))
-            res = rffi.cast(TP, ll_result)[0]
+            buf = rffi.cast(TP, ll_result)
+            if self.restype.c_type == FFI_TYPE_STRUCT:
+                # for structs, we directly return the buffer and transfer the
+                # ownership
+                res = rffi.cast(RESULT, buf)
+            else:
+                res = buf[0]
         else:
             res = None
         self._free_buffers(ll_result, ll_args)
@@ -414,7 +420,9 @@
         return res
 
     def _free_buffers(self, ll_result, ll_args):
-        if ll_result:
+        if ll_result and self.restype.c_type != FFI_TYPE_STRUCT:
+            # if it's a struct, the buffer is not freed and the ownership is
+            # transferred to the caller
             lltype.free(ll_result, flavor='raw')
         for i in range(len(self.argtypes)):
             lltype.free(ll_args[i], flavor='raw')

diff --git a/pypy/rlib/test/test_libffi.py b/pypy/rlib/test/test_libffi.py
--- a/pypy/rlib/test/test_libffi.py
+++ b/pypy/rlib/test/test_libffi.py
@@ -407,3 +407,26 @@
         res = self.call(func, [('arg_raw', adr)], rffi.LONG, init_result=0)
         assert res == 42
         lltype.free(ffi_point_struct, flavor='raw')
+
+    def test_byval_result(self):
+        """
+            struct Point make_point(long x, long y) {
+                struct Point p;
+                p.x = x;
+                p.y = y;
+                return p;
+            }
+        """
+        libfoo = CDLL(self.libfoo_name)
+        ffi_point_struct = make_struct_ffitype_e(0, 0, [types.slong, types.slong])
+        ffi_point = ffi_point_struct.ffistruct
+
+        libfoo = CDLL(self.libfoo_name)
+        make_point = (libfoo, 'make_point', [types.slong, types.slong], ffi_point)
+        #
+        PTR = lltype.Ptr(rffi.CArray(rffi.LONG))
+        p = self.call(make_point, [12, 34], PTR, init_result=0)
+        assert p[0] == 12
+        assert p[1] == 34
+        lltype.free(p, flavor='raw')
+        lltype.free(ffi_point_struct, flavor='raw')


More information about the Pypy-commit mailing list