@@ -532,6 +532,86 @@ class U(Union):
532
532
self .assertEqual (f2 , [0x4567 , 0x0123 , 0xcdef , 0x89ab ,
533
533
0x3210 , 0x7654 , 0xba98 , 0xfedc ])
534
534
535
+ def test_union_by_value (self ):
536
+ # See bpo-16575
537
+
538
+ # These should mirror the structures in Modules/_ctypes/_ctypes_test.c
539
+
540
+ class Nested1 (Structure ):
541
+ _fields_ = [
542
+ ('an_int' , c_int ),
543
+ ('another_int' , c_int ),
544
+ ]
545
+
546
+ class Test4 (Union ):
547
+ _fields_ = [
548
+ ('a_long' , c_long ),
549
+ ('a_struct' , Nested1 ),
550
+ ]
551
+
552
+ class Nested2 (Structure ):
553
+ _fields_ = [
554
+ ('an_int' , c_int ),
555
+ ('a_union' , Test4 ),
556
+ ]
557
+
558
+ class Test5 (Structure ):
559
+ _fields_ = [
560
+ ('an_int' , c_int ),
561
+ ('nested' , Nested2 ),
562
+ ('another_int' , c_int ),
563
+ ]
564
+
565
+ test4 = Test4 ()
566
+ dll = CDLL (_ctypes_test .__file__ )
567
+ with self .assertRaises (TypeError ) as ctx :
568
+ func = dll ._testfunc_union_by_value1
569
+ func .restype = c_long
570
+ func .argtypes = (Test4 ,)
571
+ result = func (test4 )
572
+ self .assertEqual (ctx .exception .args [0 ], 'item 1 in _argtypes_ passes '
573
+ 'a union by value, which is unsupported.' )
574
+ test5 = Test5 ()
575
+ with self .assertRaises (TypeError ) as ctx :
576
+ func = dll ._testfunc_union_by_value2
577
+ func .restype = c_long
578
+ func .argtypes = (Test5 ,)
579
+ result = func (test5 )
580
+ self .assertEqual (ctx .exception .args [0 ], 'item 1 in _argtypes_ passes '
581
+ 'a union by value, which is unsupported.' )
582
+
583
+ # passing by reference should be OK
584
+ test4 .a_long = 12345 ;
585
+ func = dll ._testfunc_union_by_reference1
586
+ func .restype = c_long
587
+ func .argtypes = (POINTER (Test4 ),)
588
+ result = func (byref (test4 ))
589
+ self .assertEqual (result , 12345 )
590
+ self .assertEqual (test4 .a_long , 0 )
591
+ self .assertEqual (test4 .a_struct .an_int , 0 )
592
+ self .assertEqual (test4 .a_struct .another_int , 0 )
593
+ test4 .a_struct .an_int = 0x12340000
594
+ test4 .a_struct .another_int = 0x5678
595
+ func = dll ._testfunc_union_by_reference2
596
+ func .restype = c_long
597
+ func .argtypes = (POINTER (Test4 ),)
598
+ result = func (byref (test4 ))
599
+ self .assertEqual (result , 0x12345678 )
600
+ self .assertEqual (test4 .a_long , 0 )
601
+ self .assertEqual (test4 .a_struct .an_int , 0 )
602
+ self .assertEqual (test4 .a_struct .another_int , 0 )
603
+ test5 .an_int = 0x12000000
604
+ test5 .nested .an_int = 0x345600
605
+ test5 .another_int = 0x78
606
+ func = dll ._testfunc_union_by_reference3
607
+ func .restype = c_long
608
+ func .argtypes = (POINTER (Test5 ),)
609
+ result = func (byref (test5 ))
610
+ self .assertEqual (result , 0x12345678 )
611
+ self .assertEqual (test5 .an_int , 0 )
612
+ self .assertEqual (test5 .nested .an_int , 0 )
613
+ self .assertEqual (test5 .another_int , 0 )
614
+
535
615
class PointerMemberTestCase (unittest .TestCase ):
536
616
537
617
def test (self ):
0 commit comments