Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 62a3a15

Browse files
authored
gh-107455: ctypes: Improve error messages when converting to an incompatible type (#107456)
1 parent 1cd479c commit 62a3a15

File tree

3 files changed

+62
-11
lines changed

3 files changed

+62
-11
lines changed

Lib/test/test_ctypes/test_functions.py

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import unittest
55
from ctypes import (CDLL, Structure, Array, CFUNCTYPE,
66
byref, POINTER, pointer, ArgumentError,
7-
c_char, c_wchar, c_byte, c_char_p,
8-
c_short, c_int, c_long, c_longlong,
7+
c_char, c_wchar, c_byte, c_char_p, c_wchar_p,
8+
c_short, c_int, c_long, c_longlong, c_void_p,
99
c_float, c_double, c_longdouble)
1010
from _ctypes import _Pointer, _SimpleCData
1111

@@ -92,6 +92,54 @@ def test_wchar_parm(self):
9292
"argument 2: TypeError: one character unicode string "
9393
"expected")
9494

95+
def test_c_char_p_parm(self):
96+
"""Test the error message when converting an incompatible type to c_char_p."""
97+
proto = CFUNCTYPE(c_int, c_char_p)
98+
def callback(*args):
99+
return 0
100+
101+
callback = proto(callback)
102+
self.assertEqual(callback(b"abc"), 0)
103+
104+
with self.assertRaises(ArgumentError) as cm:
105+
callback(10)
106+
107+
self.assertEqual(str(cm.exception),
108+
"argument 1: TypeError: 'int' object cannot be "
109+
"interpreted as ctypes.c_char_p")
110+
111+
def test_c_wchar_p_parm(self):
112+
"""Test the error message when converting an incompatible type to c_wchar_p."""
113+
proto = CFUNCTYPE(c_int, c_wchar_p)
114+
def callback(*args):
115+
return 0
116+
117+
callback = proto(callback)
118+
self.assertEqual(callback("abc"), 0)
119+
120+
with self.assertRaises(ArgumentError) as cm:
121+
callback(10)
122+
123+
self.assertEqual(str(cm.exception),
124+
"argument 1: TypeError: 'int' object cannot be "
125+
"interpreted as ctypes.c_wchar_p")
126+
127+
def test_c_void_p_parm(self):
128+
"""Test the error message when converting an incompatible type to c_void_p."""
129+
proto = CFUNCTYPE(c_int, c_void_p)
130+
def callback(*args):
131+
return 0
132+
133+
callback = proto(callback)
134+
self.assertEqual(callback(5), 0)
135+
136+
with self.assertRaises(ArgumentError) as cm:
137+
callback(2.5)
138+
139+
self.assertEqual(str(cm.exception),
140+
"argument 1: TypeError: 'float' object cannot be "
141+
"interpreted as ctypes.c_void_p")
142+
95143
def test_wchar_result(self):
96144
f = dll._testfunc_i_bhilfd
97145
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Improve error messages when converting an incompatible type to
2+
:class:`ctypes.c_char_p`, :class:`ctypes.c_wchar_p` and
3+
:class:`ctypes.c_void_p`.

Modules/_ctypes/_ctypes.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1728,9 +1728,9 @@ c_wchar_p_from_param(PyObject *type, PyObject *value)
17281728
Py_DECREF(as_parameter);
17291729
return value;
17301730
}
1731-
/* XXX better message */
1732-
PyErr_SetString(PyExc_TypeError,
1733-
"wrong type");
1731+
PyErr_Format(PyExc_TypeError,
1732+
"'%.200s' object cannot be interpreted "
1733+
"as ctypes.c_wchar_p", Py_TYPE(value)->tp_name);
17341734
return NULL;
17351735
}
17361736

@@ -1792,9 +1792,9 @@ c_char_p_from_param(PyObject *type, PyObject *value)
17921792
Py_DECREF(as_parameter);
17931793
return value;
17941794
}
1795-
/* XXX better message */
1796-
PyErr_SetString(PyExc_TypeError,
1797-
"wrong type");
1795+
PyErr_Format(PyExc_TypeError,
1796+
"'%.200s' object cannot be interpreted "
1797+
"as ctypes.c_char_p", Py_TYPE(value)->tp_name);
17981798
return NULL;
17991799
}
18001800

@@ -1927,9 +1927,9 @@ c_void_p_from_param(PyObject *type, PyObject *value)
19271927
Py_DECREF(as_parameter);
19281928
return value;
19291929
}
1930-
/* XXX better message */
1931-
PyErr_SetString(PyExc_TypeError,
1932-
"wrong type");
1930+
PyErr_Format(PyExc_TypeError,
1931+
"'%.200s' object cannot be interpreted "
1932+
"as ctypes.c_void_p", Py_TYPE(value)->tp_name);
19331933
return NULL;
19341934
}
19351935

0 commit comments

Comments
 (0)