[pypy-svn] r79557 - pypy/branch/fast-forward/lib_pypy/_ctypes

afa at codespeak.net afa at codespeak.net
Fri Nov 26 15:07:14 CET 2010


Author: afa
Date: Fri Nov 26 15:07:12 2010
New Revision: 79557

Modified:
   pypy/branch/fast-forward/lib_pypy/_ctypes/basics.py
   pypy/branch/fast-forward/lib_pypy/_ctypes/function.py
Log:
Fix the argument conversion:
- first try "argtype.from_param"
- then _as_parameter_
- then default guesses


Modified: pypy/branch/fast-forward/lib_pypy/_ctypes/basics.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/_ctypes/basics.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/_ctypes/basics.py	Fri Nov 26 15:07:12 2010
@@ -46,15 +46,6 @@
         else:
             return self.from_param(as_parameter)
 
-    def _CData_input(self, value):
-        """Used when data enters into ctypes from user code.  'value' is
-        some user-specified Python object, which is converted into a _rawffi
-        array of length 1 containing the same value according to the
-        type 'self'.
-        """
-        cobj = self.from_param(value)
-        return cobj, cobj._get_buffer_for_param()
-
     def _CData_value(self, value):
         cobj = self.from_param(value)
         # we don't care here if this stuff will live afterwards, as we're

Modified: pypy/branch/fast-forward/lib_pypy/_ctypes/function.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/_ctypes/function.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/_ctypes/function.py	Fri Nov 26 15:07:12 2010
@@ -54,7 +54,15 @@
         return self._argtypes_
     def _setargtypes(self, argtypes):
         self._ptr = None
-        self._argtypes_ = argtypes    
+        if argtypes is None:
+            self._argtypes_ = None
+        else:
+            for i, argtype in enumerate(argtypes):
+                if not hasattr(argtype, 'from_param'):
+                    raise TypeError(
+                        "item %d in _argtypes_ has no from_param method" % (
+                            i + 1,))
+            self._argtypes_ = argtypes
     argtypes = property(_getargtypes, _setargtypes)
 
     def _getrestype(self):
@@ -179,13 +187,15 @@
             thisarg = None
             
         if argtypes is None:
-            argtypes = self._guess_argtypes(args)
-        argtypes, argsandobjs = self._wrap_args(argtypes, args)
+            argtypes = []
+        args = self._convert_args(argtypes, args)
+        argtypes = [type(arg) for arg in args]
         
         restype = self._restype_
         funcptr = self._getfuncptr(argtypes, restype, thisarg)
-        resbuffer = funcptr(*[arg._buffer for _, arg in argsandobjs])
-        result = self._build_result(restype, resbuffer, argtypes, argsandobjs)
+        resbuffer = funcptr(*[arg._get_buffer_for_param()._buffer
+                              for arg in args])
+        result = self._build_result(restype, resbuffer, argtypes, args)
 
         # The 'errcheck' protocol
         if self._errcheck_:
@@ -243,31 +253,33 @@
             raise
 
     @staticmethod
-    def _guess_argtypes(args):
+    def _conv_param(argtype, arg, index):
         from ctypes import c_char_p, c_wchar_p, c_void_p, c_int
-        res = []
-        for arg in args:
-            if hasattr(arg, '_as_parameter_'):
-                arg = arg._as_parameter_
-            if isinstance(arg, str):
-                res.append(c_char_p)
-            elif isinstance(arg, unicode):
-                res.append(c_wchar_p)
-            elif isinstance(arg, _CData):
-                res.append(type(arg))
-            elif arg is None:
-                res.append(c_void_p)
-            #elif arg == 0:
-            #    res.append(c_void_p)
-            elif isinstance(arg, (int, long)):
-                res.append(c_int)
-            else:
-                raise TypeError("Don't know how to handle %s" % (arg,))
-        return res
+        if argtype is not None:
+            arg = argtype.from_param(arg)
+        if hasattr(arg, '_as_parameter_'):
+            arg = arg._as_parameter_
+
+        if isinstance(arg, _CData):
+            # The usual case when argtype is defined
+            cobj = arg
+        elif isinstance(arg, str):
+            cobj = c_char_p(arg)
+        elif isinstance(arg, unicode):
+            cobj = c_wchar_p(arg)
+        elif arg is None:
+            cobj = c_void_p()
+        elif isinstance(arg, (int, long)):
+            cobj = c_int(arg)
+        else:
+            raise TypeError("Don't know how to handle %s" % (arg,))
+
+        return cobj
 
-    def _wrap_args(self, argtypes, args):
+    def _convert_args(self, argtypes, args):
         wrapped_args = []
         consumed = 0
+
         for i, argtype in enumerate(argtypes):
             defaultvalue = None
             if i > 0 and self._paramflags is not None:
@@ -294,7 +306,7 @@
                     val = defaultvalue
                     if val is None:
                         val = 0
-                    wrapped = argtype._CData_input(val)
+                    wrapped = self._conv_param(argtype, val, consumed)
                     wrapped_args.append(wrapped)
                     continue
                 else:
@@ -309,23 +321,22 @@
                 raise TypeError("Not enough arguments")
 
             try:
-                wrapped = argtype._CData_input(arg)
-            except (UnicodeError, TypeError), e:
+                wrapped = self._conv_param(argtype, arg, consumed)
+            except (UnicodeError, TypeError, ValueError), e:
                 raise ArgumentError(str(e))
             wrapped_args.append(wrapped)
             consumed += 1
 
         if len(wrapped_args) < len(args):
             extra = args[len(wrapped_args):]
-            extra_types = self._guess_argtypes(extra)
-            for arg, argtype in zip(extra, extra_types):
+            argtypes = list(argtypes)
+            for i, arg in enumerate(extra):
                 try:
-                    wrapped = argtype._CData_input(arg)
-                except (UnicodeError, TypeError), e:
+                    wrapped = self._conv_param(None, arg, i)
+                except (UnicodeError, TypeError, ValueError), e:
                     raise ArgumentError(str(e))
                 wrapped_args.append(wrapped)
-            argtypes = list(argtypes) + extra_types
-        return argtypes, wrapped_args
+        return wrapped_args
 
     def _build_result(self, restype, resbuffer, argtypes, argsandobjs):
         """Build the function result:
@@ -338,7 +349,7 @@
         if self._com_index:
             if resbuffer[0] & 0x80000000:
                 raise get_com_error(resbuffer[0],
-                                    self._com_iid, argsandobjs[0][0])
+                                    self._com_iid, argsandobjs[0])
             else:
                 retval = int(resbuffer[0])
         elif restype is not None:
@@ -357,8 +368,8 @@
 
         results = []
         if self._paramflags:
-            for argtype, (obj, _), paramflag in zip(argtypes[1:], argsandobjs[1:],
-                                                    self._paramflags):
+            for argtype, obj, paramflag in zip(argtypes[1:], argsandobjs[1:],
+                                               self._paramflags):
                 if len(paramflag) == 2:
                     idlflag, name = paramflag
                 elif len(paramflag) == 3:



More information about the Pypy-commit mailing list