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

fijal at codespeak.net fijal at codespeak.net
Sun Mar 30 08:16:58 CEST 2008


Author: fijal
Date: Sun Mar 30 08:16:57 2008
New Revision: 53137

Modified:
   pypy/dist/pypy/lib/_ctypes/function.py
   pypy/dist/pypy/lib/app_test/ctypes/test_cast.py
   pypy/dist/pypy/lib/app_test/ctypes/test_cfuncs.py
   pypy/dist/pypy/lib/app_test/ctypes/test_checkretval.py
   pypy/dist/pypy/lib/app_test/ctypes/test_returnfuncptrs.py
   pypy/dist/pypy/lib/app_test/ctypes/test_simplesubclasses.py
   pypy/dist/pypy/lib/app_test/ctypes/test_values.py
Log:
* support for address parameters for CFUNCTYPE
* few minor fixes.


Modified: pypy/dist/pypy/lib/_ctypes/function.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/function.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/function.py	Sun Mar 30 08:16:57 2008
@@ -1,8 +1,9 @@
 
-import types
 from _ctypes.basics import _CData, _CDataMeta, ArgumentError, keepalive_key
 import _rawffi
 
+# XXX this file needs huge refactoring I fear
+
 class CFuncPtrType(_CDataMeta):
     # XXX write down here defaults and such things
 
@@ -24,6 +25,9 @@
     _ffishape = 'P'
     _fficompositesize = None
     _needs_free = False
+    callable = None
+    _ptr = None
+    _buffer = None
 
     def _getargtypes(self):
         return self._argtypes_
@@ -37,30 +41,34 @@
         if restype is int:
             from ctypes import c_int
             restype = c_int
-        if not isinstance(restype, _CDataMeta) and not restype is None:
+        if not isinstance(restype, _CDataMeta) and not restype is None and \
+               not callable(restype):
             raise TypeError("Expected ctypes type, got %s" % (restype,))
         self._restype_ = restype
-    restype = property(_getrestype, _setrestype)    
+    restype = property(_getrestype, _setrestype)
+
+    def _ffishapes(self, args, restype):
+        argtypes = [arg._ffiargshape for arg in args]
+        if restype is not None:
+            restype = restype._ffiargshape
+        else:
+            restype = 'O' # void
+        return argtypes, restype
 
     def __init__(self, argument=None):
-        self.callable = None
         self.name = None
         self._objects = {keepalive_key(0):self}
-        if isinstance(argument, int):
-            self._buffer = _rawffi.Array('P').fromaddress(argument, 1)
-            # XXX finish this one, we need to be able to jump there somehow
+        self._needs_free = True
+        if isinstance(argument, (int, long)):
+            ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_)
+            self._ptr = _rawffi.FuncPtr(argument, ffiargs, ffires)
+            self._buffer = self._ptr.byptr()
         elif callable(argument):
             self.callable = argument
-            argtypes = [arg._ffiargshape for arg in self._argtypes_]
-            restype = self._restype_
-            if restype is not None:
-                restype = restype._ffiargshape
-            else:
-                restype = 'O' # void
+            ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_)
             self._ptr = _rawffi.CallbackPtr(self._wrap_callable(argument,
                                                                 self.argtypes),
-                                            argtypes, restype)
-            self._needs_free = True
+                                            ffiargs, ffires)
             self._buffer = self._ptr.byptr()
         elif isinstance(argument, tuple) and len(argument) == 2:
             import ctypes
@@ -68,11 +76,12 @@
             if isinstance(self.dll, str):
                 self.dll = ctypes.CDLL(self.dll)
             # we need to check dll anyway
-            self._getfuncptr([], ctypes.c_int)
+            ptr = self._getfuncptr([], ctypes.c_int)
+            self._buffer = ptr.byptr()
         elif argument is None:
+            # this is needed for casts
             self._buffer = _rawffi.Array('P')(1)
-            self._needs_free = True
-            return # needed for test..
+            return
         else:
             raise TypeError("Unknown constructor %s" % (argument,))
 
@@ -86,7 +95,10 @@
     
     def __call__(self, *args):
         if self.callable is not None:
-            return self.callable(*args)
+            res = self.callable(*args)
+            if self._restype_ is not None:
+                return res
+            return
         argtypes = self._argtypes_
         if argtypes is None:
             argtypes = self._guess_argtypes(args)
@@ -102,14 +114,21 @@
         args = self._wrap_args(argtypes, args)
         resbuffer = funcptr(*[arg._buffer for obj, arg in args])
         if restype is not None:
+            if not isinstance(restype, _CDataMeta):
+                return restype(resbuffer[0])
             return restype._CData_retval(resbuffer)
 
     def _getfuncptr(self, argtypes, restype):
-        if restype is None:
+        if self._ptr is not None:
+            return self._ptr
+        if restype is None or not isinstance(restype, _CDataMeta):
             import ctypes
             restype = ctypes.c_int
         argshapes = [arg._ffiargshape for arg in argtypes]
         resshape = restype._ffiargshape
+        if self._buffer is not None:
+            self._ptr = _rawffi.FuncPtr(self._buffer[0], argshapes, resshape)
+            return self._ptr
         return self.dll._handle.ptr(self.name, argshapes, resshape)
 
     def _guess_argtypes(self, args):
@@ -144,7 +163,7 @@
         if self._needs_free:
             self._buffer.free()
             self._buffer = None
-            if hasattr(self, '_ptr'):
+            if isinstance(self._ptr, _rawffi.CallbackPtr):
                 self._ptr.free()
                 self._ptr = None
-                self._needs_free = False
+            self._needs_free = False

Modified: pypy/dist/pypy/lib/app_test/ctypes/test_cast.py
==============================================================================
--- pypy/dist/pypy/lib/app_test/ctypes/test_cast.py	(original)
+++ pypy/dist/pypy/lib/app_test/ctypes/test_cast.py	Sun Mar 30 08:16:57 2008
@@ -2,6 +2,10 @@
 import sys, py
 from support import BaseCTypesTestChecker
 
+def setup_module(mod):
+    import conftest
+    mod.lib = CDLL(str(conftest.sofile))
+
 class TestCast(BaseCTypesTestChecker):
 
     def test_array2pointer(self):
@@ -77,5 +81,7 @@
 
     def test_cast_functype(self):
         # make sure we can cast function type
-        P = CFUNCTYPE(c_int)
-        cast(1, P)
+        my_sqrt = lib.my_sqrt
+        sqrt = cast(cast(my_sqrt, c_void_p), CFUNCTYPE(c_double, c_double))
+        assert sqrt(4.0) == 2.0
+        

Modified: pypy/dist/pypy/lib/app_test/ctypes/test_cfuncs.py
==============================================================================
--- pypy/dist/pypy/lib/app_test/ctypes/test_cfuncs.py	(original)
+++ pypy/dist/pypy/lib/app_test/ctypes/test_cfuncs.py	Sun Mar 30 08:16:57 2008
@@ -163,7 +163,6 @@
         assert self.S() == 42
 
     def test_callwithresult(self):
-        py.test.skip("function as restype unsupported")
         def process_result(result):
             return result * 2
         self._dll.tf_i.restype = process_result

Modified: pypy/dist/pypy/lib/app_test/ctypes/test_checkretval.py
==============================================================================
--- pypy/dist/pypy/lib/app_test/ctypes/test_checkretval.py	(original)
+++ pypy/dist/pypy/lib/app_test/ctypes/test_checkretval.py	Sun Mar 30 08:16:57 2008
@@ -16,7 +16,7 @@
 class TestRetval:
 
     def test_checkretval(self):
-        py.test.skip("restype being a function not implemented")
+        py.test.skip("_check_retval_ is not supported")
 
         assert 42 == dll._testfunc_p_p(42)
 

Modified: pypy/dist/pypy/lib/app_test/ctypes/test_returnfuncptrs.py
==============================================================================
--- pypy/dist/pypy/lib/app_test/ctypes/test_returnfuncptrs.py	(original)
+++ pypy/dist/pypy/lib/app_test/ctypes/test_returnfuncptrs.py	Sun Mar 30 08:16:57 2008
@@ -9,7 +9,6 @@
 class TestReturnFuncPtr:
 
     def test_with_prototype(self):
-        py.test.skip("returning functions doesn't work")
         # The _ctypes_test shared lib/dll exports quite some functions for testing.
         # The get_strchr function returns a *pointer* to the C strchr function.
         get_strchr = dll.get_strchr
@@ -21,7 +20,6 @@
         raises(TypeError, strchr, "abcdef")
 
     def test_without_prototype(self):
-        py.test.skip("constructing functions from address doesn't work")
         get_strchr = dll.get_strchr
         # the default 'c_int' would not work on systems where sizeof(int) != sizeof(void *)
         get_strchr.restype = c_void_p

Modified: pypy/dist/pypy/lib/app_test/ctypes/test_simplesubclasses.py
==============================================================================
--- pypy/dist/pypy/lib/app_test/ctypes/test_simplesubclasses.py	(original)
+++ pypy/dist/pypy/lib/app_test/ctypes/test_simplesubclasses.py	Sun Mar 30 08:16:57 2008
@@ -15,7 +15,6 @@
         assert not MyInt(42) == MyInt(43)
 
     def test_ignore_retval(self):
-        py.test.skip("XXX different callback behavior")
         # Test if the return value of a callback is ignored
         # if restype is None
         proto = CFUNCTYPE(None)
@@ -27,7 +26,7 @@
 
 
     def test_int_callback(self):
-        py.test.skip("XXX different callback behavior")
+        py.test.skip("XXX subclassing not implemented")
         args = []
         def func(arg):
             args.append(arg)

Modified: pypy/dist/pypy/lib/app_test/ctypes/test_values.py
==============================================================================
--- pypy/dist/pypy/lib/app_test/ctypes/test_values.py	(original)
+++ pypy/dist/pypy/lib/app_test/ctypes/test_values.py	Sun Mar 30 08:16:57 2008
@@ -26,7 +26,7 @@
 class TestWin_Values(BaseCTypesTestChecker):
     """This test only works when python itself is a dll/shared library"""
     def setup_class(cls):
-        py.test.skip("not implemented")
+        py.test.skip("only when cpython itself is a dll")
 
     def test_optimizeflag(self):
         # This test accesses the Py_OptimizeFlag intger, which is



More information about the Pypy-commit mailing list