183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport os, unittest
283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom ctypes import *
383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehtry:
583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    WINFUNCTYPE
683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehexcept NameError:
783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # fake to enable this test on Linux
883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    WINFUNCTYPE = CFUNCTYPE
983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport _ctypes_test
1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehlib = CDLL(_ctypes_test.__file__)
1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass CFuncPtrTestCase(unittest.TestCase):
1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def test_basic(self):
1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        X = WINFUNCTYPE(c_int, c_int, c_int)
1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def func(*args):
1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return len(args)
1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        x = X(func)
2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(x.restype, c_int)
2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(x.argtypes, (c_int, c_int))
2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(sizeof(x), sizeof(c_voidp))
2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(sizeof(X), sizeof(c_voidp))
2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def test_first(self):
2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        StdCallback = WINFUNCTYPE(c_int, c_int, c_int)
2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        CdeclCallback = CFUNCTYPE(c_int, c_int, c_int)
2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def func(a, b):
3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return a + b
3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        s = StdCallback(func)
3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        c = CdeclCallback(func)
3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(s(1, 2), 3)
3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(c(1, 2), 3)
3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # The following no longer raises a TypeError - it is now
3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # possible, as in C, to call cdecl functions with more parameters.
4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        #self.assertRaises(TypeError, c, 1, 2, 3)
4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(c(1, 2, 3, 4, 5, 6), 3)
4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not WINFUNCTYPE is CFUNCTYPE and os.name != "ce":
4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.assertRaises(TypeError, s, 1, 2, 3)
4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def test_structures(self):
4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        WNDPROC = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int)
4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def wndproc(hwnd, msg, wParam, lParam):
4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return hwnd + msg + wParam + lParam
5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        HINSTANCE = c_int
5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        HICON = c_int
5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        HCURSOR = c_int
5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        LPCTSTR = c_char_p
5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        class WNDCLASS(Structure):
5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            _fields_ = [("style", c_uint),
5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        ("lpfnWndProc", WNDPROC),
5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        ("cbClsExtra", c_int),
6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        ("cbWndExtra", c_int),
6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        ("hInstance", HINSTANCE),
6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        ("hIcon", HICON),
6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        ("hCursor", HCURSOR),
6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        ("lpszMenuName", LPCTSTR),
6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        ("lpszClassName", LPCTSTR)]
6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        wndclass = WNDCLASS()
6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        wndclass.lpfnWndProc = WNDPROC(wndproc)
6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        WNDPROC_2 = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int)
7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # This is no longer true, now that WINFUNCTYPE caches created types internally.
7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ## # CFuncPtr subclasses are compared by identity, so this raises a TypeError:
7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ## self.assertRaises(TypeError, setattr, wndclass,
7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ##                  "lpfnWndProc", WNDPROC_2(wndproc))
7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # instead:
7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertTrue(WNDPROC is WNDPROC_2)
7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # 'wndclass.lpfnWndProc' leaks 94 references.  Why?
8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(wndclass.lpfnWndProc(1, 2, 3, 4), 10)
8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        f = wndclass.lpfnWndProc
8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        del wndclass
8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        del wndproc
8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(f(10, 11, 12, 13), 46)
8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def test_dllfunctions(self):
9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def NoNullHandle(value):
9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if not value:
9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                raise WinError()
9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return value
9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        strchr = lib.my_strchr
9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        strchr.restype = c_char_p
9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        strchr.argtypes = (c_char_p, c_char)
10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(strchr("abcdefghi", "b"), "bcdefghi")
10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(strchr("abcdefghi", "x"), None)
10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        strtok = lib.my_strtok
10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        strtok.restype = c_char_p
10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Neither of this does work: strtok changes the buffer it is passed
10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh##        strtok.argtypes = (c_char_p, c_char_p)
10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh##        strtok.argtypes = (c_string, c_char_p)
10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def c_string(init):
11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            size = len(init) + 1
11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return (c_char*size)(*init)
11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        s = "a\nb\nc"
11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        b = c_string(s)
11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh##        b = (c_char * (len(s)+1))()
11883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh##        b.value = s
11983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
12083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh##        b = c_string(s)
12183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(strtok(b, "\n"), "a")
12283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(strtok(None, "\n"), "b")
12383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(strtok(None, "\n"), "c")
12483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(strtok(None, "\n"), None)
12583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
12683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehif __name__ == '__main__':
12783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    unittest.main()
128