|
4 | 4 | import sys
|
5 | 5 | import operator
|
6 | 6 | import pytest
|
| 7 | +import ctypes |
7 | 8 |
|
8 | 9 | import numpy as np
|
9 | 10 | from numpy.core._rational_tests import rational
|
@@ -728,3 +729,74 @@ def test_dtypes_are_true():
|
728 | 729 | def test_invalid_dtype_string():
|
729 | 730 | # test for gh-10440
|
730 | 731 | assert_raises(TypeError, np.dtype, 'f8,i8,[f8,i8]')
|
| 732 | + |
| 733 | + |
| 734 | +class TestFromCTypes(object): |
| 735 | + |
| 736 | + @staticmethod |
| 737 | + def check(ctype, dtype): |
| 738 | + dtype = np.dtype(dtype) |
| 739 | + assert_equal(np.dtype(ctype), dtype) |
| 740 | + assert_equal(np.dtype(ctype()), dtype) |
| 741 | + |
| 742 | + def test_array(self): |
| 743 | + c8 = ctypes.c_uint8 |
| 744 | + self.check( 3 * c8, (np.uint8, (3,))) |
| 745 | + self.check( 1 * c8, (np.uint8, (1,))) |
| 746 | + self.check( 0 * c8, (np.uint8, (0,))) |
| 747 | + self.check(1 * (3 * c8), ((np.uint8, (3,)), (1,))) |
| 748 | + self.check(3 * (1 * c8), ((np.uint8, (1,)), (3,))) |
| 749 | + |
| 750 | + def test_padded_structure(self): |
| 751 | + class PaddedStruct(ctypes.Structure): |
| 752 | + _fields_ = [ |
| 753 | + ('a', ctypes.c_uint8), |
| 754 | + ('b', ctypes.c_uint16) |
| 755 | + ] |
| 756 | + expected = np.dtype([ |
| 757 | + ('a', np.uint8), |
| 758 | + ('b', np.uint16) |
| 759 | + ], align=True) |
| 760 | + self.check(PaddedStruct, expected) |
| 761 | + |
| 762 | + @pytest.mark.xfail(reason="_pack_ is ignored - see gh-11651") |
| 763 | + def test_packed_structure(self): |
| 764 | + class PackedStructure(ctypes.Structure): |
| 765 | + _pack_ = 1 |
| 766 | + _fields_ = [ |
| 767 | + ('a', ctypes.c_uint8), |
| 768 | + ('b', ctypes.c_uint16) |
| 769 | + ] |
| 770 | + expected = np.dtype([ |
| 771 | + ('a', np.uint8), |
| 772 | + ('b', np.uint16) |
| 773 | + ]) |
| 774 | + self.check(PackedStructure, expected) |
| 775 | + |
| 776 | + @pytest.mark.xfail(sys.byteorder != 'little', |
| 777 | + reason="non-native endianness does not work - see gh-10533") |
| 778 | + def test_little_endian_structure(self): |
| 779 | + class PaddedStruct(ctypes.LittleEndianStructure): |
| 780 | + _fields_ = [ |
| 781 | + ('a', ctypes.c_uint8), |
| 782 | + ('b', ctypes.c_uint16) |
| 783 | + ] |
| 784 | + expected = np.dtype([ |
| 785 | + ('a', '<B'), |
| 786 | + ('b', '<H') |
| 787 | + ], align=True) |
| 788 | + self.check(PaddedStruct, expected) |
| 789 | + |
| 790 | + @pytest.mark.xfail(sys.byteorder != 'big', |
| 791 | + reason="non-native endianness does not work - see gh-10533") |
| 792 | + def test_big_endian_structure(self): |
| 793 | + class PaddedStruct(ctypes.BigEndianStructure): |
| 794 | + _fields_ = [ |
| 795 | + ('a', ctypes.c_uint8), |
| 796 | + ('b', ctypes.c_uint16) |
| 797 | + ] |
| 798 | + expected = np.dtype([ |
| 799 | + ('a', '>B'), |
| 800 | + ('b', '>H') |
| 801 | + ], align=True) |
| 802 | + self.check(PaddedStruct, expected) |