[pypy-svn] r51617 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes

fijal at codespeak.net fijal at codespeak.net
Tue Feb 19 00:32:23 CET 2008


Author: fijal
Date: Tue Feb 19 00:32:21 2008
New Revision: 51617

Modified:
   pypy/dist/pypy/lib/_ctypes/array.py
   pypy/dist/pypy/lib/_ctypes/basics.py
   pypy/dist/pypy/lib/_ctypes/structure.py
   pypy/dist/pypy/lib/app_test/ctypes/test_structures.py
Log:
* A bit of simplification
* Forest of ifs what we support and what we don't in terms of args
  for arrays
* Structure/Array inlining now shall work.


Modified: pypy/dist/pypy/lib/_ctypes/array.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/array.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/array.py	Tue Feb 19 00:32:21 2008
@@ -3,6 +3,7 @@
 
 from _ctypes.basics import _CData, cdata_from_address, _CDataMeta, sizeof,\
      keepalive_key, store_reference, CArgObject
+from _ctypes.builtin import _string_at_addr, _wstring_at_addr
 
 def _create_unicode(buffer, maxlength):
     res = []
@@ -71,6 +72,12 @@
         return self._type_._alignmentofinstances()
 
     def _CData_output(self, resarray, base=None, index=-1):
+        # this seems to be a string if we're array of char, surprise!
+        from ctypes import c_char, c_wchar, c_char_p, c_wchar_p
+        if self._type_ is c_char:
+            return _rawffi.charp2string(resarray.buffer, self._length_)
+        if self._type_ is c_wchar:
+            xxx
         res = self.__new__(self)
         ffiarray = self._ffiarray.fromaddress(resarray.buffer, self._length_)
         res._buffer = ffiarray
@@ -78,6 +85,22 @@
         res._index = index
         return res.__ctypes_from_outparam__()
 
+    def _CData_value(self, value):
+        # array accepts very strange parameters as part of structure
+        # or function argument...
+        from ctypes import c_char, c_wchar
+        if issubclass(self._type_, (c_char, c_wchar)):
+            if isinstance(value, basestring):
+                if len(value) > self._length_:
+                    raise ValueError("Invalid length")
+                return self(*value)
+        else:
+            if isinstance(value, tuple):
+                if len(value) > self._length_:
+                    raise RuntimeError("Invalid length")
+                return self(*value)
+        return _CDataMeta._CData_value(self, value)
+
 def array_get_slice_params(self, index):
     if index.step is not None:
         raise TypeError("3 arg slices not supported (for no reason)")
@@ -158,6 +181,9 @@
     def _get_buffer_for_param(self):
         return CArgObject(self._buffer.byptr())
 
+    def _get_buffer_value(self):
+        return self._buffer.buffer
+
     def __del__(self):
         if self._needs_free:
             self._buffer.free()

Modified: pypy/dist/pypy/lib/_ctypes/basics.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/basics.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/basics.py	Tue Feb 19 00:32:21 2008
@@ -45,7 +45,7 @@
         cobj = self.from_param(value)
         # we don't care here if this stuff will live afterwards, as we're
         # interested only in value anyway
-        return cobj._get_buffer_for_param()._buffer[0]
+        return cobj._get_buffer_value()
 
     def _CData_output(self, resarray, base=None, index=-1, needs_free=False):
         assert isinstance(resarray, _rawffi.ArrayInstance)
@@ -99,6 +99,9 @@
     def _get_buffer_for_param(self):
         return self
 
+    def _get_buffer_value(self):
+        return self._buffer[0]
+
 def sizeof(tp):
     if not isinstance(tp, _CDataMeta):
         if isinstance(tp, _CData):

Modified: pypy/dist/pypy/lib/_ctypes/structure.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/structure.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/structure.py	Tue Feb 19 00:32:21 2008
@@ -141,6 +141,11 @@
     def _alignmentofinstances(self):
         return self._ffistruct.alignment
 
+    def _CData_value(self, value):
+        if isinstance(value, tuple):
+            return self(*value)
+        return _CDataMeta._CData_value(self, value)
+
     def _CData_output(self, resarray, base=None, index=-1):
         res = self.__new__(self)
         ffistruct = self._ffistruct.fromaddress(resarray.buffer)
@@ -169,7 +174,13 @@
         if getattr(value, '_objects', None):
             key = keepalive_key(getattr(self.__class__, name).offset)
             store_reference(self, key, value._objects)
-        self._buffer.__setattr__(name, fieldtype._CData_value(value))
+        arg = fieldtype._CData_value(value)
+        if isinstance(fieldtype._ffishape, tuple):
+            from ctypes import memmove
+            dest = self._buffer.fieldaddress(name)
+            memmove(dest, arg._buffer.buffer, fieldtype._ffishape[0])
+        else:
+            self._buffer.__setattr__(name, arg)
 
     def __getattribute__(self, name):
         if name == '_fieldtypes':
@@ -185,6 +196,9 @@
     def _get_buffer_for_param(self):
         return CArgObject(self._buffer.byptr())
 
+    def _get_buffer_value(self):
+        return self._buffer.buffer
+
     def __del__(self):
         if self._needs_free:
             self._buffer.free()

Modified: pypy/dist/pypy/lib/app_test/ctypes/test_structures.py
==============================================================================
--- pypy/dist/pypy/lib/app_test/ctypes/test_structures.py	(original)
+++ pypy/dist/pypy/lib/app_test/ctypes/test_structures.py	Tue Feb 19 00:32:21 2008
@@ -161,7 +161,7 @@
         # offset is always relative to the class...
 
     def test_packed(self):
-        py.test.skip("???")
+        py.test.skip("Custom alignment not supported")
         class X(Structure):
             _fields_ = [("a", c_byte),
                         ("b", c_longlong)]
@@ -203,7 +203,6 @@
         raises(ValueError, type(Structure), "X", (Structure,), d)
 
     def test_initializers(self):
-        py.test.skip("Structures with inlined arrays")
         class Person(Structure):
             _fields_ = [("name", c_char*6),
                         ("age", c_int)]
@@ -235,7 +234,6 @@
         raises(TypeError, setattr, POINT, "_fields_", [("x", 1), ("y", 2)])
 
     def test_intarray_fields(self):
-        py.test.skip("Structures with inlined arrays")
         class SomeInts(Structure):
             _fields_ = [("a", c_int * 4)]
 
@@ -247,7 +245,6 @@
         raises(RuntimeError, SomeInts, (1, 2, 3, 4, 5))
 
     def test_nested_initializers(self):
-        py.test.skip("???")
         # test initializing nested structures
         class Phone(Structure):
             _fields_ = [("areacode", c_char*6),
@@ -266,7 +263,7 @@
         assert p.age == 5
 
     def test_structures_with_wchar(self):
-        py.test.skip("Inlined array")
+        py.test.skip("need unicode support on _rawffi level")
         try:
             c_wchar
         except NameError:
@@ -287,7 +284,7 @@
         raises(ValueError, PersonW, u"1234567890123")
 
     def test_init_errors(self):
-        py.test.skip("???")
+        py.test.skip("Very fragile errors")
         class Phone(Structure):
             _fields_ = [("areacode", c_char*6),
                         ("number", c_char*12)]
@@ -334,7 +331,7 @@
 ##                             (AttributeError, "class must define a '_fields_' attribute"))
 
     def test_abstract_class(self):
-        py.test.skip("???")
+        py.test.skip("What is _abstract_?")
         class X(Structure):
             _abstract_ = "something"
         # try 'X()'
@@ -405,7 +402,7 @@
 
 
     def test_vice_versa(self):
-        py.test.skip("???")
+        py.test.skip("I don't understand this test at all")
         class First(Structure):
             pass
         class Second(Structure):



More information about the Pypy-commit mailing list