text: from ctypes import *
  import pytest
  from .support import BaseCTypesTestChecker
  
  class TestCallbacks(BaseCTypesTestChecker):
      functype = CFUNCTYPE
  
  ##    def tearDown(self):
  ##        import gc
  ##        gc.collect()
  
      def callback(self, *args):
          self.got_args = args
          return args[-1]
  
      def check_type(self, typ, arg):
          unwrapped_types = {
              c_float: (float,),
              c_double: (float,),
              c_char: (str,),
              c_char_p: (str,),
              c_uint: (int, long),
              c_ulong: (int, long),
              }
  
          PROTO = self.functype.im_func(typ, typ)
          cfunc = PROTO(self.callback)
          result = cfunc(arg)
          if typ == c_float:
              assert abs(result - arg) < 0.000001
          else:
              assert self.got_args == (arg,)
              assert result == arg
  
          result2 = cfunc(typ(arg))
          assert type(result2) in unwrapped_types.get(typ, (int, long))
  
          PROTO = self.functype.im_func(typ, c_byte, typ)
          result = PROTO(self.callback)(-3, arg)
          if typ == c_float:
              assert abs(result - arg) < 0.000001
          else:
              assert self.got_args == (-3, arg)
              assert result == arg
  
      ################
  
      def test_byte(self):
          self.check_type(c_byte, 42)
          self.check_type(c_byte, -42)
  
      def test_ubyte(self):
          self.check_type(c_ubyte, 42)
  
      def test_short(self):
          self.check_type(c_short, 42)
          self.check_type(c_short, -42)
  
      def test_ushort(self):
          self.check_type(c_ushort, 42)
  
      def test_int(self):
          self.check_type(c_int, 42)
          self.check_type(c_int, -42)
  
      def test_uint(self):
          self.check_type(c_uint, 42)
  
      def test_long(self):
          self.check_type(c_long, 42)
          self.check_type(c_long, -42)
  
      def test_ulong(self):
          self.check_type(c_ulong, 42)
  
      def test_longlong(self):
          self.check_type(c_longlong, 42)
          self.check_type(c_longlong, -42)
  
      def test_ulonglong(self):
          self.check_type(c_ulonglong, 42)
  
      def test_float(self):
          # only almost equal: double -> float -> double
          import math
          self.check_type(c_float, math.e)
          self.check_type(c_float, -math.e)
  
      def test_double(self):
          self.check_type(c_double, 3.14)
          self.check_type(c_double, -3.14)
  
      def test_char(self):
          self.check_type(c_char, "x")
          self.check_type(c_char, "a")
  
      # disabled: would now (correctly) raise a RuntimeWarning about
      # a memory leak.  A callback function cannot return a non-integral
      # C type without causing a memory leak.
  ##    def test_char_p(self):
  ##        self.check_type(c_char_p, "abc")
  ##        self.check_type(c_char_p, "def")
  
  
      @pytest.mark.xfail(
          reason="we are less strict about callback return type sanity")
      def test_unsupported_restype_1(self):
          # Only "fundamental" result types are supported for callback
          # functions, the type must have a non-NULL stgdict->setfunc.
          # POINTER(c_double), for example, is not supported.
  
          prototype = self.functype.im_func(POINTER(c_double))
          # The type is checked when the prototype is called
          with pytest.raises(TypeError):
              prototype(lambda: None)
  
  try:
      WINFUNCTYPE
  except NameError:
      pass
  else:
      class TestStdcallCallbacks(TestCallbacks):
          functype = WINFUNCTYPE
  
  ################################################################
  
  class TestSampleCallbacks(BaseCTypesTestChecker):
  
      def test_integrate(self):
          # Derived from some then non-working code, posted by David Foster
          import conftest
          _ctypes_test = str(conftest.sofile)
          dll = CDLL(_ctypes_test)
  
          # The function prototype called by 'integrate': double func(double);
          CALLBACK = CFUNCTYPE(c_double, c_double)
  
          # The integrate function itself, exposed from the _ctypes_test dll
          integrate = dll.integrate
          integrate.argtypes = (c_double, c_double, CALLBACK, c_long)
          integrate.restype = c_double
  
          def func(x):
              print 'calculating x**2 of',x
              return x**2
  
          result = integrate(0.0, 1.0, CALLBACK(func), 10)
          diff = abs(result - 1./3.)
  
          assert diff < 0.01, "%s not less than 0.01" % diff
  
  ################################################################
  
  class TestMoreCallbacks(BaseCTypesTestChecker):
  
      def test_callback_with_struct_argument(self):
          class RECT(Structure):
              _fields_ = [("left", c_int), ("top", c_int),
                          ("right", c_int), ("bottom", c_int)]
  
          proto = CFUNCTYPE(c_int, RECT)
          def callback(point):
              return point.left+point.top+point.right+point.bottom
  
          cbp = proto(callback)
  
          rect = RECT(1000,100,10,1)
  
          res = cbp(rect)
  
          assert res == 1111
  
      def test_callback_from_c_with_struct_argument(self):
          import conftest
          _ctypes_test = str(conftest.sofile)
          dll = CDLL(_ctypes_test)
  
          class RECT(Structure):
              _fields_ = [("left", c_long), ("top", c_long),
                          ("right", c_long), ("bottom", c_long)]
  
          proto = CFUNCTYPE(c_int, RECT)
          def callback(point):
              return point.left+point.top+point.right+point.bottom
  
          cbp = proto(callback)
          rect = RECT(1000,100,10,1)
  
          call_callback_with_rect = dll.call_callback_with_rect
          call_callback_with_rect.restype = c_int
          call_callback_with_rect.argtypes = [proto, RECT]
          res = call_callback_with_rect(cbp, rect)
          assert res == 1111
  
      def test_callback_unsupported_return_struct(self):
          class RECT(Structure):
              _fields_ = [("left", c_int), ("top", c_int),
                          ("right", c_int), ("bottom", c_int)]
  
          proto = CFUNCTYPE(RECT, c_int)
          with pytest.raises(TypeError):
              proto(lambda r: 0)
  
  
      def test_qsort(self):
          import conftest
          _ctypes_test = str(conftest.sofile)
          dll = CDLL(_ctypes_test)
  
          PI = POINTER(c_int)
          A = c_int*5
          a = A()
          for i in range(5):
              a[i] = 5-i
  
          assert a[0] == 5 # sanity
  
          def comp(a, b):
              a = a.contents.value
              b = b.contents.value
              return cmp(a,b)
          qs = dll.my_qsort
          qs.restype = None
          CMP = CFUNCTYPE(c_int, PI, PI)
          qs.argtypes = (PI, c_size_t, c_size_t, CMP)
  
          qs(cast(a, PI), 5, sizeof(c_int), CMP(comp))
  
          res = list(a)
  
          assert res == [1,2,3,4,5]
  
      def test_pyobject_as_opaque(self):
          import conftest
          _ctypes_test = str(conftest.sofile)
          dll = CDLL(_ctypes_test)
  
          def callback(arg):
              return arg()
  
          CTP = CFUNCTYPE(c_int, py_object)
          cfunc = dll._testfunc_callback_opaque
          cfunc.argtypes = [CTP, py_object]
          cfunc.restype = c_int
          res = cfunc(CTP(callback), lambda : 3)
          assert res == 3
  
      def test_callback_void(self, capsys):
          import conftest
          _ctypes_test = str(conftest.sofile)
          dll = CDLL(_ctypes_test)
  
          def callback():
              pass
  
          CTP = CFUNCTYPE(None)
          cfunc = dll._testfunc_callback_void
          cfunc.argtypes = [CTP]
          cfunc.restype = int
          cfunc(CTP(callback))
          out, err = capsys.readouterr()
          assert (out, err) == ("", "")
  
  
      def test_callback_pyobject(self):
          def callback(obj):
              return obj
  
          FUNC = CFUNCTYPE(py_object, py_object)
          cfunc = FUNC(callback)
          param = c_int(42)
          assert cfunc(param) is param
  
      def test_raise_argumenterror(self):
          def callback(x):
              pass
          FUNC = CFUNCTYPE(None, c_void_p)
          cfunc = FUNC(callback)
          param = c_uint(42)
          with pytest.raises(ArgumentError):
              cfunc(param)
  