[pypy-svn] r51590 - pypy/dist/pypy/lib/_ctypes

fijal at codespeak.net fijal at codespeak.net
Mon Feb 18 17:01:39 CET 2008


Author: fijal
Date: Mon Feb 18 17:01:39 2008
New Revision: 51590

Modified:
   pypy/dist/pypy/lib/_ctypes/array.py
   pypy/dist/pypy/lib/_ctypes/basics.py
   pypy/dist/pypy/lib/_ctypes/builtin.py
   pypy/dist/pypy/lib/_ctypes/function.py
   pypy/dist/pypy/lib/_ctypes/pointer.py
   pypy/dist/pypy/lib/_ctypes/structure.py
   pypy/dist/pypy/lib/_ctypes/union.py
Log:
Slightly more subtle approach to freeing stuff. Let's see how it works out.
Also, this has quite a bit of indirection, I think we shall start from writing
tests for what we know about this now...


Modified: pypy/dist/pypy/lib/_ctypes/array.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/array.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/array.py	Mon Feb 18 17:01:39 2008
@@ -2,7 +2,7 @@
 import _rawffi
 
 from _ctypes.basics import _CData, cdata_from_address, _CDataMeta, sizeof,\
-     keepalive_key
+     keepalive_key, CArgObject
 
 def _create_unicode(buffer, maxlength):
     res = []
@@ -129,14 +129,14 @@
         index = self._fix_index(index)
         if getattr(value, '_objects', None):
             self._objects[keepalive_key(index)] = value._objects
-        cobj, value = self._type_._CData_input(value)
+        cobj, arg = self._type_._CData_input(value)
         if not isinstance(self._type_._ffishape, tuple):
-            self._buffer[index] = value[0]
+            self._buffer[index] = arg._buffer[0]
             # something more sophisticated, cannot set field directly
         else:
             from ctypes import memmove
             dest = self._buffer.itemaddress(index)
-            source = value[0]
+            source = arg._buffer[0]
             memmove(dest, source, self._type_._ffishape[0])
 
     def __getitem__(self, index):
@@ -149,7 +149,7 @@
         return self._length_
 
     def _get_buffer_for_param(self):
-        return self._buffer.byptr()
+        return CArgObject(self._buffer.byptr())
 
     def __del__(self):
         if self._needs_free:

Modified: pypy/dist/pypy/lib/_ctypes/basics.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/basics.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/basics.py	Mon Feb 18 17:01:39 2008
@@ -39,11 +39,9 @@
         type 'self'.
         """
         cobj = self.from_param(value)
-        # XXX this function segfaults randomly, because
-        # cobj is considered to be an owner of that, fix
         return cobj, cobj._get_buffer_for_param()
 
-    def _CData_output(self, resarray, base=None, index=-1):
+    def _CData_output(self, resarray, base=None, index=-1, needs_free=False):
         assert isinstance(resarray, _rawffi.ArrayInstance)
         """Used when data exits ctypes and goes into user code.
         'resarray' is a _rawffi array of length 1 containing the value,
@@ -53,6 +51,7 @@
         res.__dict__['_buffer'] = resarray
         res.__dict__['_base'] = base
         res.__dict__['_index'] = index
+        res.__dict__['_needs_free'] = needs_free
         return res.__ctypes_from_outparam__()
 
     def __mul__(self, other):
@@ -68,6 +67,17 @@
         val._buffer = buffer
         return val
 
+class CArgObject(object):
+    """ simple wrapper around buffer, just for the case of freeing
+    it afterwards
+    """
+    def __init__(self, buffer):
+        self._buffer = buffer
+
+    def __del__(self):
+        self._buffer.free()
+        self._buffer = None
+
 class _CData(object):
     """ The most basic object for all ctypes types
     """
@@ -81,17 +91,7 @@
         return self
 
     def _get_buffer_for_param(self):
-        return self._buffer
-
-#class CArgObject(object):
-#    def __init__(self, letter, raw_value, _type):
-#        self.ffiletter = letter
-#        self._array = raw_value
-#        self._type = _type
-
-#    def __repr__(self):
-#        return "<cparam '%s' %r>" % (self.ffiletter, self._array[0])
-
+        return self
 
 def sizeof(tp):
     if not isinstance(tp, _CDataMeta):

Modified: pypy/dist/pypy/lib/_ctypes/builtin.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/builtin.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/builtin.py	Mon Feb 18 17:01:39 2008
@@ -12,7 +12,7 @@
     # address here can be almost anything
     import ctypes
     cobj, arg = ctypes.c_char_p._CData_input(addr)
-    obj = arg[0]
+    obj = arg._buffer[0]
     return _rawffi.charp2rawstring(obj, lgt)
 
 def set_conversion_mode(encoding, errors):
@@ -24,7 +24,7 @@
 def _wstring_at_addr(addr, lgt):
     import ctypes
     cobj, arg = ctypes.c_wchar_p._CData_input(addr)
-    obj = arg[0]
+    obj = arg._buffer[0]
     # XXX purely applevel
     if lgt == -1:
         lgt = sys.maxint

Modified: pypy/dist/pypy/lib/_ctypes/function.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/function.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/function.py	Mon Feb 18 17:01:39 2008
@@ -78,9 +78,11 @@
         restype = self._restype_
         funcptr = self._getfuncptr(argtypes, restype)
         args = self._wrap_args(argtypes, args)
-        resarray = funcptr(*[arg for obj, arg in args])
+        resarray = funcptr(*[arg._buffer for obj, arg in args])
         if restype is not None:
-            return restype._CData_output(resarray)
+            return restype._CData_output(resarray, needs_free=True)
+        else:
+            resarray.free()
 
     def _getfuncptr(self, argtypes, restype):
         if restype is None:

Modified: pypy/dist/pypy/lib/_ctypes/pointer.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/pointer.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/pointer.py	Mon Feb 18 17:01:39 2008
@@ -101,7 +101,7 @@
 
     def __setitem__(self, index, value):
         cobj, arg = self._type_._CData_input(value)
-        self._subarray(index)[0] = arg[0]
+        self._subarray(index)[0] = arg._buffer[0]
 
     def __nonzero__(self):
         return self._buffer[0] != 0

Modified: pypy/dist/pypy/lib/_ctypes/structure.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/structure.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/structure.py	Mon Feb 18 17:01:39 2008
@@ -1,7 +1,7 @@
 
 import _rawffi
 from _ctypes.basics import _CData, _CDataMeta, keepalive_key,\
-     store_reference
+     store_reference, CArgObject
 import inspect
 
 def round_up(size, alignment):
@@ -168,8 +168,8 @@
         if getattr(value, '_objects', None):
             key = keepalive_key(getattr(self.__class__, name).offset)
             store_reference(self, key, value._objects)
-        cobj, value = fieldtype._CData_input(value)
-        self._buffer.__setattr__(name, value[0])
+        cobj, arg = fieldtype._CData_input(value)
+        self._buffer.__setattr__(name, arg._buffer[0])
 
     def __getattribute__(self, name):
         if name == '_fieldtypes':
@@ -183,7 +183,7 @@
                                        offset)
 
     def _get_buffer_for_param(self):
-        return self._buffer.byptr()
+        return CArgObject(self._buffer.byptr())
 
     def __del__(self):
         if self._needs_free:

Modified: pypy/dist/pypy/lib/_ctypes/union.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/union.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/union.py	Mon Feb 18 17:01:39 2008
@@ -81,9 +81,9 @@
             fieldtype = self._fieldtypes[name].ctype
         except KeyError:
             raise AttributeError(name)
-        cobj, value = fieldtype._CData_input(value)
+        cobj, arg = fieldtype._CData_input(value)
         buf = self._ffiarrays[name].fromaddress(self._buffer.buffer, 1)
-        buf[0] = value[0]
+        buf[0] = arg._buffer[0]
 
     def __del__(self):
         if self._needs_free:



More information about the Pypy-commit mailing list