diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py index 8f6fe5f..6ec6ef3 100644 --- a/Lib/ctypes/test/test_structures.py +++ b/Lib/ctypes/test/test_structures.py @@ -3,6 +3,7 @@ from ctypes import * from ctypes.test import need_symbol from struct import calcsize import _testcapi +import _ctypes_test class SubclassesTest(unittest.TestCase): def test_subclass(self): @@ -391,6 +392,28 @@ class StructureTestCase(unittest.TestCase): (1, 0, 0, 0, 0, 0)) self.assertRaises(TypeError, lambda: Z(1, 2, 3, 4, 5, 6, 7)) + def test_array_in_struct(self): + # This should mirror the structure in Modules/_ctypes/_ctypes_test.c + class Test2(Structure): + _fields_ = [ + ('data', c_ubyte * 16), + ] + + s = Test2() + expected = 0 + for i in range(16): + s.data[i] = i + expected += i + dll = CDLL(_ctypes_test.__file__) + func = dll._testfunc_array_in_struct + func.restype = c_int + func.argtypes = (Test2,) + result = func(s) + self.assertEqual(result, expected) + # check the passed-in struct hasn't changed + for i in range(16): + self.assertEqual(s.data[i], i) + class PointerMemberTestCase(unittest.TestCase): def test(self): diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c index 92b5adb..35799b8 100644 --- a/Modules/_ctypes/_ctypes_test.c +++ b/Modules/_ctypes/_ctypes_test.c @@ -44,6 +44,24 @@ _testfunc_cbk_large_struct(Test in, void (*func)(Test)) func(in); } +typedef struct { + unsigned char data[16]; +} Test2; + +EXPORT(int) +_testfunc_array_in_struct(Test2 in) +{ + int result = 0; + + for (unsigned i = 0; i < 16; i++) + result += in.data[i]; + /* As the structure is passed by value, changes to it shouldn't be + * reflected in the caller. + */ + memset(in.data, 0, sizeof(in.data)); + return result; +} + EXPORT(void)testfunc_array(int values[4]) { printf("testfunc_array %d %d %d %d\n",