Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 5dc4fe0

Browse filesBrowse files
author
Thomas Heller
committed
Patch #1649190: Adding support for _Bool to ctypes as c_bool, by David Remahl.
1 parent 8441f15 commit 5dc4fe0
Copy full SHA for 5dc4fe0

File tree

Expand file treeCollapse file tree

10 files changed

+656
-50
lines changed
Filter options
Expand file treeCollapse file tree

10 files changed

+656
-50
lines changed

‎Doc/lib/libctypes.tex

Copy file name to clipboardExpand all lines: Doc/lib/libctypes.tex
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2294,6 +2294,12 @@ \subsubsection{Fundamental data types\label{ctypes-fundamental-data-types}}
22942294
an integer address, or a string.
22952295
\end{classdesc*}
22962296
2297+
\begin{classdesc*}{c_bool}
2298+
Represent the C \code{bool} datatype (more accurately, _Bool from C99).
2299+
Its value can be True or False, and the constructor accepts any object that
2300+
has a truth value.
2301+
\end{classdesc*}
2302+
22972303
\begin{classdesc*}{HRESULT}
22982304
Windows only: Represents a \class{HRESULT} value, which contains success
22992305
or error information for a function or method call.

‎Lib/ctypes/__init__.py

Copy file name to clipboardExpand all lines: Lib/ctypes/__init__.py
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ class c_void_p(_SimpleCData):
233233
c_voidp = c_void_p # backwards compatibility (to a bug)
234234
_check_size(c_void_p)
235235

236+
class c_bool(_SimpleCData):
237+
_type_ = "t"
238+
236239
# This cache maps types to pointers to them.
237240
_pointer_type_cache = {}
238241

‎Lib/ctypes/test/test_numbers.py

Copy file name to clipboardExpand all lines: Lib/ctypes/test/test_numbers.py
+29-2Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ def valid_ranges(*types):
2424
unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong]
2525
signed_types = [c_byte, c_short, c_int, c_long, c_longlong]
2626

27+
bool_types = []
28+
2729
float_types = [c_double, c_float]
2830

2931
try:
@@ -35,8 +37,16 @@ def valid_ranges(*types):
3537
unsigned_types.append(c_ulonglong)
3638
signed_types.append(c_longlong)
3739

40+
try:
41+
c_bool
42+
except NameError:
43+
pass
44+
else:
45+
bool_types.append(c_bool)
46+
3847
unsigned_ranges = valid_ranges(*unsigned_types)
3948
signed_ranges = valid_ranges(*signed_types)
49+
bool_values = [True, False, 0, 1, -1, 5000, 'test', [], [1]]
4050

4151
################################################################
4252

@@ -59,6 +69,11 @@ def test_signed_values(self):
5969
for t, (l, h) in zip(signed_types, signed_ranges):
6070
self.failUnlessEqual(t(l).value, l)
6171
self.failUnlessEqual(t(h).value, h)
72+
73+
def test_bool_values(self):
74+
from operator import truth
75+
for t, v in zip(bool_types, bool_values):
76+
self.failUnlessEqual(t(v).value, truth(v))
6277

6378
def test_typeerror(self):
6479
# Only numbers are allowed in the contructor,
@@ -82,7 +97,7 @@ def test_from_param(self):
8297

8398
def test_byref(self):
8499
# calling byref returns also a PyCArgObject instance
85-
for t in signed_types + unsigned_types + float_types:
100+
for t in signed_types + unsigned_types + float_types + bool_types:
86101
parm = byref(t())
87102
self.failUnlessEqual(ArgType, type(parm))
88103

@@ -101,7 +116,7 @@ def test_integers(self):
101116
self.assertRaises(TypeError, t, 3.14)
102117

103118
def test_sizes(self):
104-
for t in signed_types + unsigned_types + float_types:
119+
for t in signed_types + unsigned_types + float_types + bool_types:
105120
size = struct.calcsize(t._type_)
106121
# sizeof of the type...
107122
self.failUnlessEqual(sizeof(t), size)
@@ -163,6 +178,18 @@ def test_char_from_address(self):
163178

164179
a[0] = '?'
165180
self.failUnlessEqual(v.value, a[0])
181+
182+
# array does not support c_bool / 't'
183+
# def test_bool_from_address(self):
184+
# from ctypes import c_bool
185+
# from array import array
186+
# a = array(c_bool._type_, [True])
187+
# v = t.from_address(a.buffer_info()[0])
188+
# self.failUnlessEqual(v.value, a[0])
189+
# self.failUnlessEqual(type(v) is t)
190+
# a[0] = False
191+
# self.failUnlessEqual(v.value, a[0])
192+
# self.failUnlessEqual(type(v) is t)
166193

167194
def test_init(self):
168195
# c_int() can be initialized from Python's int, and c_int.

‎Lib/ctypes/test/test_repr.py

Copy file name to clipboardExpand all lines: Lib/ctypes/test/test_repr.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
subclasses = []
55
for base in [c_byte, c_short, c_int, c_long, c_longlong,
66
c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong,
7-
c_float, c_double]:
7+
c_float, c_double, c_bool]:
88
class X(base):
99
pass
1010
subclasses.append(X)

‎Misc/NEWS

Copy file name to clipboardExpand all lines: Misc/NEWS
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ Core and builtins
168168
Library
169169
-------
170170

171+
- Patch #1649190: Adding support for _Bool to ctypes as c_bool.
172+
171173
- Patch #1530482: add pydoc.render_doc() which returns the documentation
172174
for a thing instead of paging it to stdout, which pydoc.doc() does.
173175

‎Modules/_ctypes/_ctypes.c

Copy file name to clipboardExpand all lines: Modules/_ctypes/_ctypes.c
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,7 @@ _type_ attribute.
11011101
11021102
*/
11031103

1104-
static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv";
1104+
static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOvt";
11051105

11061106
static PyObject *
11071107
c_wchar_p_from_param(PyObject *type, PyObject *value)

‎Modules/_ctypes/cfield.c

Copy file name to clipboardExpand all lines: Modules/_ctypes/cfield.c
+40Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,35 @@ vBOOL_get(void *ptr, unsigned size)
725725
}
726726
#endif
727727

728+
#ifdef HAVE_C99_BOOL
729+
#define BOOL_TYPE _Bool
730+
#else
731+
#define BOOL_TYPE char
732+
#undef SIZEOF__BOOL
733+
#define SIZEOF__BOOL 1
734+
#endif
735+
736+
static PyObject *
737+
t_set(void *ptr, PyObject *value, unsigned size)
738+
{
739+
switch (PyObject_IsTrue(value)) {
740+
case -1:
741+
return NULL;
742+
case 0:
743+
*(BOOL_TYPE *)ptr = 0;
744+
_RET(value);
745+
default:
746+
*(BOOL_TYPE *)ptr = 1;
747+
_RET(value);
748+
}
749+
}
750+
751+
static PyObject *
752+
t_get(void *ptr, unsigned size)
753+
{
754+
return PyBool_FromLong((long)*(BOOL_TYPE *)ptr);
755+
}
756+
728757
static PyObject *
729758
I_set(void *ptr, PyObject *value, unsigned size)
730759
{
@@ -1585,6 +1614,17 @@ static struct fielddesc formattable[] = {
15851614
{ 'X', BSTR_set, BSTR_get, &ffi_type_pointer},
15861615
{ 'v', vBOOL_set, vBOOL_get, &ffi_type_sshort},
15871616
#endif
1617+
#if SIZEOF__BOOL == 1
1618+
{ 't', t_set, t_get, &ffi_type_uchar}, /* Also fallback for no native _Bool support */
1619+
#elif SIZEOF__BOOL == SIZEOF_SHORT
1620+
{ 't', t_set, t_get, &ffi_type_ushort},
1621+
#elif SIZEOF__BOOL == SIZEOF_INT
1622+
{ 't', t_set, t_get, &ffi_type_uint, I_set_sw, I_get_sw},
1623+
#elif SIZEOF__BOOL == SIZEOF_LONG
1624+
{ 't', t_set, t_get, &ffi_type_ulong, L_set_sw, L_get_sw},
1625+
#elif SIZEOF__BOOL == SIZEOF_LONG_LONG
1626+
{ 't', t_set, t_get, &ffi_type_ulong, Q_set_sw, Q_get_sw},
1627+
#endif /* SIZEOF__BOOL */
15881628
{ 'O', O_set, O_get, &ffi_type_pointer},
15891629
{ 0, NULL, NULL, NULL},
15901630
};

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.