PageRenderTime 25ms CodeModel.GetById 5ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/ctypes/test/test_funcptr.py

http://unladen-swallow.googlecode.com/
Python | 127 lines | 80 code | 31 blank | 16 comment | 6 complexity | 910303d64b2b5585e8ede93434ff7ef6 MD5 | raw file
  1import os, unittest
  2from ctypes import *
  3
  4try:
  5    WINFUNCTYPE
  6except NameError:
  7    # fake to enable this test on Linux
  8    WINFUNCTYPE = CFUNCTYPE
  9
 10import _ctypes_test
 11lib = CDLL(_ctypes_test.__file__)
 12
 13class CFuncPtrTestCase(unittest.TestCase):
 14    def test_basic(self):
 15        X = WINFUNCTYPE(c_int, c_int, c_int)
 16
 17        def func(*args):
 18            return len(args)
 19
 20        x = X(func)
 21        self.failUnlessEqual(x.restype, c_int)
 22        self.failUnlessEqual(x.argtypes, (c_int, c_int))
 23        self.failUnlessEqual(sizeof(x), sizeof(c_voidp))
 24        self.failUnlessEqual(sizeof(X), sizeof(c_voidp))
 25
 26    def test_first(self):
 27        StdCallback = WINFUNCTYPE(c_int, c_int, c_int)
 28        CdeclCallback = CFUNCTYPE(c_int, c_int, c_int)
 29
 30        def func(a, b):
 31            return a + b
 32
 33        s = StdCallback(func)
 34        c = CdeclCallback(func)
 35
 36        self.failUnlessEqual(s(1, 2), 3)
 37        self.failUnlessEqual(c(1, 2), 3)
 38        # The following no longer raises a TypeError - it is now
 39        # possible, as in C, to call cdecl functions with more parameters.
 40        #self.assertRaises(TypeError, c, 1, 2, 3)
 41        self.failUnlessEqual(c(1, 2, 3, 4, 5, 6), 3)
 42        if not WINFUNCTYPE is CFUNCTYPE and os.name != "ce":
 43            self.assertRaises(TypeError, s, 1, 2, 3)
 44
 45    def test_structures(self):
 46        WNDPROC = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int)
 47
 48        def wndproc(hwnd, msg, wParam, lParam):
 49            return hwnd + msg + wParam + lParam
 50
 51        HINSTANCE = c_int
 52        HICON = c_int
 53        HCURSOR = c_int
 54        LPCTSTR = c_char_p
 55
 56        class WNDCLASS(Structure):
 57            _fields_ = [("style", c_uint),
 58                        ("lpfnWndProc", WNDPROC),
 59                        ("cbClsExtra", c_int),
 60                        ("cbWndExtra", c_int),
 61                        ("hInstance", HINSTANCE),
 62                        ("hIcon", HICON),
 63                        ("hCursor", HCURSOR),
 64                        ("lpszMenuName", LPCTSTR),
 65                        ("lpszClassName", LPCTSTR)]
 66
 67        wndclass = WNDCLASS()
 68        wndclass.lpfnWndProc = WNDPROC(wndproc)
 69
 70        WNDPROC_2 = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int)
 71
 72        # This is no longer true, now that WINFUNCTYPE caches created types internally.
 73        ## # CFuncPtr subclasses are compared by identity, so this raises a TypeError:
 74        ## self.assertRaises(TypeError, setattr, wndclass,
 75        ##                  "lpfnWndProc", WNDPROC_2(wndproc))
 76        # instead:
 77
 78        self.failUnless(WNDPROC is WNDPROC_2)
 79        # 'wndclass.lpfnWndProc' leaks 94 references.  Why?
 80        self.failUnlessEqual(wndclass.lpfnWndProc(1, 2, 3, 4), 10)
 81
 82
 83        f = wndclass.lpfnWndProc
 84
 85        del wndclass
 86        del wndproc
 87
 88        self.failUnlessEqual(f(10, 11, 12, 13), 46)
 89
 90    def test_dllfunctions(self):
 91
 92        def NoNullHandle(value):
 93            if not value:
 94                raise WinError()
 95            return value
 96
 97        strchr = lib.my_strchr
 98        strchr.restype = c_char_p
 99        strchr.argtypes = (c_char_p, c_char)
100        self.failUnlessEqual(strchr("abcdefghi", "b"), "bcdefghi")
101        self.failUnlessEqual(strchr("abcdefghi", "x"), None)
102
103
104        strtok = lib.my_strtok
105        strtok.restype = c_char_p
106        # Neither of this does work: strtok changes the buffer it is passed
107##        strtok.argtypes = (c_char_p, c_char_p)
108##        strtok.argtypes = (c_string, c_char_p)
109
110        def c_string(init):
111            size = len(init) + 1
112            return (c_char*size)(*init)
113
114        s = "a\nb\nc"
115        b = c_string(s)
116
117##        b = (c_char * (len(s)+1))()
118##        b.value = s
119
120##        b = c_string(s)
121        self.failUnlessEqual(strtok(b, "\n"), "a")
122        self.failUnlessEqual(strtok(None, "\n"), "b")
123        self.failUnlessEqual(strtok(None, "\n"), "c")
124        self.failUnlessEqual(strtok(None, "\n"), None)
125
126if __name__ == '__main__':
127    unittest.main()