Commit 5dc4fe09 authored by Thomas Heller's avatar Thomas Heller

Patch #1649190: Adding support for _Bool to ctypes as c_bool, by David Remahl.

parent 8441f156
...@@ -2294,6 +2294,12 @@ a zero-terminated wide character string. The constructor accepts ...@@ -2294,6 +2294,12 @@ a zero-terminated wide character string. The constructor accepts
an integer address, or a string. an integer address, or a string.
\end{classdesc*} \end{classdesc*}
\begin{classdesc*}{c_bool}
Represent the C \code{bool} datatype (more accurately, _Bool from C99).
Its value can be True or False, and the constructor accepts any object that
has a truth value.
\end{classdesc*}
\begin{classdesc*}{HRESULT} \begin{classdesc*}{HRESULT}
Windows only: Represents a \class{HRESULT} value, which contains success Windows only: Represents a \class{HRESULT} value, which contains success
or error information for a function or method call. or error information for a function or method call.
......
...@@ -233,6 +233,9 @@ class c_void_p(_SimpleCData): ...@@ -233,6 +233,9 @@ class c_void_p(_SimpleCData):
c_voidp = c_void_p # backwards compatibility (to a bug) c_voidp = c_void_p # backwards compatibility (to a bug)
_check_size(c_void_p) _check_size(c_void_p)
class c_bool(_SimpleCData):
_type_ = "t"
# This cache maps types to pointers to them. # This cache maps types to pointers to them.
_pointer_type_cache = {} _pointer_type_cache = {}
......
...@@ -24,6 +24,8 @@ ArgType = type(byref(c_int(0))) ...@@ -24,6 +24,8 @@ ArgType = type(byref(c_int(0)))
unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong] unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong]
signed_types = [c_byte, c_short, c_int, c_long, c_longlong] signed_types = [c_byte, c_short, c_int, c_long, c_longlong]
bool_types = []
float_types = [c_double, c_float] float_types = [c_double, c_float]
try: try:
...@@ -35,8 +37,16 @@ else: ...@@ -35,8 +37,16 @@ else:
unsigned_types.append(c_ulonglong) unsigned_types.append(c_ulonglong)
signed_types.append(c_longlong) signed_types.append(c_longlong)
try:
c_bool
except NameError:
pass
else:
bool_types.append(c_bool)
unsigned_ranges = valid_ranges(*unsigned_types) unsigned_ranges = valid_ranges(*unsigned_types)
signed_ranges = valid_ranges(*signed_types) signed_ranges = valid_ranges(*signed_types)
bool_values = [True, False, 0, 1, -1, 5000, 'test', [], [1]]
################################################################ ################################################################
...@@ -59,6 +69,11 @@ class NumberTestCase(unittest.TestCase): ...@@ -59,6 +69,11 @@ class NumberTestCase(unittest.TestCase):
for t, (l, h) in zip(signed_types, signed_ranges): for t, (l, h) in zip(signed_types, signed_ranges):
self.failUnlessEqual(t(l).value, l) self.failUnlessEqual(t(l).value, l)
self.failUnlessEqual(t(h).value, h) self.failUnlessEqual(t(h).value, h)
def test_bool_values(self):
from operator import truth
for t, v in zip(bool_types, bool_values):
self.failUnlessEqual(t(v).value, truth(v))
def test_typeerror(self): def test_typeerror(self):
# Only numbers are allowed in the contructor, # Only numbers are allowed in the contructor,
...@@ -82,7 +97,7 @@ class NumberTestCase(unittest.TestCase): ...@@ -82,7 +97,7 @@ class NumberTestCase(unittest.TestCase):
def test_byref(self): def test_byref(self):
# calling byref returns also a PyCArgObject instance # calling byref returns also a PyCArgObject instance
for t in signed_types + unsigned_types + float_types: for t in signed_types + unsigned_types + float_types + bool_types:
parm = byref(t()) parm = byref(t())
self.failUnlessEqual(ArgType, type(parm)) self.failUnlessEqual(ArgType, type(parm))
...@@ -101,7 +116,7 @@ class NumberTestCase(unittest.TestCase): ...@@ -101,7 +116,7 @@ class NumberTestCase(unittest.TestCase):
self.assertRaises(TypeError, t, 3.14) self.assertRaises(TypeError, t, 3.14)
def test_sizes(self): def test_sizes(self):
for t in signed_types + unsigned_types + float_types: for t in signed_types + unsigned_types + float_types + bool_types:
size = struct.calcsize(t._type_) size = struct.calcsize(t._type_)
# sizeof of the type... # sizeof of the type...
self.failUnlessEqual(sizeof(t), size) self.failUnlessEqual(sizeof(t), size)
...@@ -163,6 +178,18 @@ class NumberTestCase(unittest.TestCase): ...@@ -163,6 +178,18 @@ class NumberTestCase(unittest.TestCase):
a[0] = '?' a[0] = '?'
self.failUnlessEqual(v.value, a[0]) self.failUnlessEqual(v.value, a[0])
# array does not support c_bool / 't'
# def test_bool_from_address(self):
# from ctypes import c_bool
# from array import array
# a = array(c_bool._type_, [True])
# v = t.from_address(a.buffer_info()[0])
# self.failUnlessEqual(v.value, a[0])
# self.failUnlessEqual(type(v) is t)
# a[0] = False
# self.failUnlessEqual(v.value, a[0])
# self.failUnlessEqual(type(v) is t)
def test_init(self): def test_init(self):
# c_int() can be initialized from Python's int, and c_int. # c_int() can be initialized from Python's int, and c_int.
......
...@@ -4,7 +4,7 @@ import unittest ...@@ -4,7 +4,7 @@ import unittest
subclasses = [] subclasses = []
for base in [c_byte, c_short, c_int, c_long, c_longlong, for base in [c_byte, c_short, c_int, c_long, c_longlong,
c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong, c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong,
c_float, c_double]: c_float, c_double, c_bool]:
class X(base): class X(base):
pass pass
subclasses.append(X) subclasses.append(X)
......
...@@ -168,6 +168,8 @@ Core and builtins ...@@ -168,6 +168,8 @@ Core and builtins
Library Library
------- -------
- Patch #1649190: Adding support for _Bool to ctypes as c_bool.
- Patch #1530482: add pydoc.render_doc() which returns the documentation - Patch #1530482: add pydoc.render_doc() which returns the documentation
for a thing instead of paging it to stdout, which pydoc.doc() does. for a thing instead of paging it to stdout, which pydoc.doc() does.
......
...@@ -1101,7 +1101,7 @@ _type_ attribute. ...@@ -1101,7 +1101,7 @@ _type_ attribute.
*/ */
static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv"; static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOvt";
static PyObject * static PyObject *
c_wchar_p_from_param(PyObject *type, PyObject *value) c_wchar_p_from_param(PyObject *type, PyObject *value)
......
...@@ -725,6 +725,35 @@ vBOOL_get(void *ptr, unsigned size) ...@@ -725,6 +725,35 @@ vBOOL_get(void *ptr, unsigned size)
} }
#endif #endif
#ifdef HAVE_C99_BOOL
#define BOOL_TYPE _Bool
#else
#define BOOL_TYPE char
#undef SIZEOF__BOOL
#define SIZEOF__BOOL 1
#endif
static PyObject *
t_set(void *ptr, PyObject *value, unsigned size)
{
switch (PyObject_IsTrue(value)) {
case -1:
return NULL;
case 0:
*(BOOL_TYPE *)ptr = 0;
_RET(value);
default:
*(BOOL_TYPE *)ptr = 1;
_RET(value);
}
}
static PyObject *
t_get(void *ptr, unsigned size)
{
return PyBool_FromLong((long)*(BOOL_TYPE *)ptr);
}
static PyObject * static PyObject *
I_set(void *ptr, PyObject *value, unsigned size) I_set(void *ptr, PyObject *value, unsigned size)
{ {
...@@ -1585,6 +1614,17 @@ static struct fielddesc formattable[] = { ...@@ -1585,6 +1614,17 @@ static struct fielddesc formattable[] = {
{ 'X', BSTR_set, BSTR_get, &ffi_type_pointer}, { 'X', BSTR_set, BSTR_get, &ffi_type_pointer},
{ 'v', vBOOL_set, vBOOL_get, &ffi_type_sshort}, { 'v', vBOOL_set, vBOOL_get, &ffi_type_sshort},
#endif #endif
#if SIZEOF__BOOL == 1
{ 't', t_set, t_get, &ffi_type_uchar}, /* Also fallback for no native _Bool support */
#elif SIZEOF__BOOL == SIZEOF_SHORT
{ 't', t_set, t_get, &ffi_type_ushort},
#elif SIZEOF__BOOL == SIZEOF_INT
{ 't', t_set, t_get, &ffi_type_uint, I_set_sw, I_get_sw},
#elif SIZEOF__BOOL == SIZEOF_LONG
{ 't', t_set, t_get, &ffi_type_ulong, L_set_sw, L_get_sw},
#elif SIZEOF__BOOL == SIZEOF_LONG_LONG
{ 't', t_set, t_get, &ffi_type_ulong, Q_set_sw, Q_get_sw},
#endif /* SIZEOF__BOOL */
{ 'O', O_set, O_get, &ffi_type_pointer}, { 'O', O_set, O_get, &ffi_type_pointer},
{ 0, NULL, NULL, NULL}, { 0, NULL, NULL, NULL},
}; };
......
This diff is collapsed.
...@@ -106,6 +106,17 @@ if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then ...@@ -106,6 +106,17 @@ if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
fi fi
AC_SUBST(HAVE_LONG_DOUBLE) AC_SUBST(HAVE_LONG_DOUBLE)
AC_MSG_CHECKING(for _Bool support)
have_c99_bool=no
AC_TRY_COMPILE([], [_Bool x; x = (_Bool)0;], [
AC_DEFINE(HAVE_C99_BOOL, 1, [Define this if you have the type _Bool.])
have_c99_bool=yes
])
AC_MSG_RESULT($have_c99_bool)
if test "$have_c99_bool" = yes ; then
AC_CHECK_SIZEOF(_Bool, 1)
fi
AC_C_BIGENDIAN AC_C_BIGENDIAN
AH_VERBATIM([WORDS_BIGENDIAN], AH_VERBATIM([WORDS_BIGENDIAN],
[ [
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
*/ */
#undef HAVE_AS_SPARC_UA_PCREL #undef HAVE_AS_SPARC_UA_PCREL
/* Define this if you have the type _Bool. */
#undef HAVE_C99_BOOL
/* Define if __attribute__((visibility("hidden"))) is supported. */ /* Define if __attribute__((visibility("hidden"))) is supported. */
#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE #undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
...@@ -103,6 +106,9 @@ ...@@ -103,6 +106,9 @@
/* The size of a `long double', as computed by sizeof. */ /* The size of a `long double', as computed by sizeof. */
#undef SIZEOF_LONG_DOUBLE #undef SIZEOF_LONG_DOUBLE
/* The size of a `_Bool', as computed by sizeof. */
#undef SIZEOF__BOOL
/* If using the C implementation of alloca, define if you know the /* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be direction of stack growth for your system; otherwise it will be
automatically deduced at run-time. automatically deduced at run-time.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment