Home | History | Annotate | Download | only in test
      1 import os, unittest
      2 from ctypes import *
      3 
      4 try:
      5     WINFUNCTYPE
      6 except NameError:
      7     # fake to enable this test on Linux
      8     WINFUNCTYPE = CFUNCTYPE
      9 
     10 import _ctypes_test
     11 lib = CDLL(_ctypes_test.__file__)
     12 
     13 class 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.assertEqual(x.restype, c_int)
     22         self.assertEqual(x.argtypes, (c_int, c_int))
     23         self.assertEqual(sizeof(x), sizeof(c_voidp))
     24         self.assertEqual(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.assertEqual(s(1, 2), 3)
     37         self.assertEqual(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.assertEqual(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.assertTrue(WNDPROC is WNDPROC_2)
     79         # 'wndclass.lpfnWndProc' leaks 94 references.  Why?
     80         self.assertEqual(wndclass.lpfnWndProc(1, 2, 3, 4), 10)
     81 
     82 
     83         f = wndclass.lpfnWndProc
     84 
     85         del wndclass
     86         del wndproc
     87 
     88         self.assertEqual(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.assertEqual(strchr("abcdefghi", "b"), "bcdefghi")
    101         self.assertEqual(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.assertEqual(strtok(b, "\n"), "a")
    122         self.assertEqual(strtok(None, "\n"), "b")
    123         self.assertEqual(strtok(None, "\n"), "c")
    124         self.assertEqual(strtok(None, "\n"), None)
    125 
    126 if __name__ == '__main__':
    127     unittest.main()
    128