summaryrefslogtreecommitdiffstats
path: root/Lib/ctypes
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/ctypes')
-rw-r--r--Lib/ctypes/__init__.py7
-rw-r--r--Lib/ctypes/test/test_functions.py14
-rw-r--r--Lib/ctypes/test/test_memfunctions.py2
-rw-r--r--Lib/ctypes/test/test_numbers.py31
-rw-r--r--Lib/ctypes/test/test_repr.py2
5 files changed, 50 insertions, 6 deletions
diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py
index e2ea426..bd9b66e 100644
--- a/Lib/ctypes/__init__.py
+++ b/Lib/ctypes/__init__.py
@@ -233,6 +233,9 @@ class c_void_p(_SimpleCData):
c_voidp = c_void_p # backwards compatibility (to a bug)
_check_size(c_void_p)
+class c_bool(_SimpleCData):
+ _type_ = "t"
+
# This cache maps types to pointers to them.
_pointer_type_cache = {}
@@ -480,7 +483,7 @@ def cast(obj, typ):
return _cast(obj, obj, typ)
_string_at = CFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
-def string_at(ptr, size=0):
+def string_at(ptr, size=-1):
"""string_at(addr[, size]) -> string
Return the string at addr."""
@@ -492,7 +495,7 @@ except ImportError:
pass
else:
_wstring_at = CFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr)
- def wstring_at(ptr, size=0):
+ def wstring_at(ptr, size=-1):
"""wstring_at(addr[, size]) -> string
Return the string at addr."""
diff --git a/Lib/ctypes/test/test_functions.py b/Lib/ctypes/test/test_functions.py
index e907e21..40892b9 100644
--- a/Lib/ctypes/test/test_functions.py
+++ b/Lib/ctypes/test/test_functions.py
@@ -21,7 +21,9 @@ if sys.platform == "win32":
class POINT(Structure):
_fields_ = [("x", c_int), ("y", c_int)]
-
+class RECT(Structure):
+ _fields_ = [("left", c_int), ("top", c_int),
+ ("right", c_int), ("bottom", c_int)]
class FunctionTestCase(unittest.TestCase):
def test_mro(self):
@@ -379,5 +381,15 @@ class FunctionTestCase(unittest.TestCase):
self.failUnlessEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h),
(9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
+ def test_sf1651235(self):
+ # see http://www.python.org/sf/1651235
+
+ proto = CFUNCTYPE(c_int, RECT, POINT)
+ def callback(*args):
+ return 0
+
+ callback = proto(callback)
+ self.failUnlessRaises(ArgumentError, lambda: callback((1, 2, 3, 4), POINT()))
+
if __name__ == '__main__':
unittest.main()
diff --git a/Lib/ctypes/test/test_memfunctions.py b/Lib/ctypes/test/test_memfunctions.py
index fbae2ce..aef7a73 100644
--- a/Lib/ctypes/test/test_memfunctions.py
+++ b/Lib/ctypes/test/test_memfunctions.py
@@ -14,6 +14,7 @@ class MemFunctionsTest(unittest.TestCase):
self.failUnlessEqual(string_at(result), "Hello, World")
self.failUnlessEqual(string_at(result, 5), "Hello")
self.failUnlessEqual(string_at(result, 16), "Hello, World\0\0\0\0")
+ self.failUnlessEqual(string_at(result, 0), "")
def test_memset(self):
a = create_string_buffer(1000000)
@@ -54,6 +55,7 @@ class MemFunctionsTest(unittest.TestCase):
self.failUnlessEqual(wstring_at(a), "Hello, World")
self.failUnlessEqual(wstring_at(a, 5), "Hello")
self.failUnlessEqual(wstring_at(a, 16), "Hello, World\0\0\0\0")
+ self.failUnlessEqual(wstring_at(a, 0), "")
if __name__ == "__main__":
unittest.main()
diff --git a/Lib/ctypes/test/test_numbers.py b/Lib/ctypes/test/test_numbers.py
index 2c5a990..eaabc7c 100644
--- a/Lib/ctypes/test/test_numbers.py
+++ b/Lib/ctypes/test/test_numbers.py
@@ -24,6 +24,8 @@ ArgType = type(byref(c_int(0)))
unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong]
signed_types = [c_byte, c_short, c_int, c_long, c_longlong]
+bool_types = []
+
float_types = [c_double, c_float]
try:
@@ -35,8 +37,16 @@ else:
unsigned_types.append(c_ulonglong)
signed_types.append(c_longlong)
+try:
+ c_bool
+except NameError:
+ pass
+else:
+ bool_types.append(c_bool)
+
unsigned_ranges = valid_ranges(*unsigned_types)
signed_ranges = valid_ranges(*signed_types)
+bool_values = [True, False, 0, 1, -1, 5000, 'test', [], [1]]
################################################################
@@ -60,6 +70,11 @@ class NumberTestCase(unittest.TestCase):
self.failUnlessEqual(t(l).value, l)
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):
# Only numbers are allowed in the contructor,
# otherwise TypeError is raised
@@ -82,7 +97,7 @@ class NumberTestCase(unittest.TestCase):
def test_byref(self):
# 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())
self.failUnlessEqual(ArgType, type(parm))
@@ -101,7 +116,7 @@ class NumberTestCase(unittest.TestCase):
self.assertRaises(TypeError, t, 3.14)
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_)
# sizeof of the type...
self.failUnlessEqual(sizeof(t), size)
@@ -164,6 +179,18 @@ class NumberTestCase(unittest.TestCase):
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):
# c_int() can be initialized from Python's int, and c_int.
# Not from c_long or so, which seems strange, abd should
diff --git a/Lib/ctypes/test/test_repr.py b/Lib/ctypes/test/test_repr.py
index 1044f67..f6f9366 100644
--- a/Lib/ctypes/test/test_repr.py
+++ b/Lib/ctypes/test/test_repr.py
@@ -4,7 +4,7 @@ import unittest
subclasses = []
for base in [c_byte, c_short, c_int, c_long, c_longlong,
c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong,
- c_float, c_double]:
+ c_float, c_double, c_bool]:
class X(base):
pass
subclasses.append(X)