]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-107455: ctypes: Improve error messages when converting to an incompatible type...
authorTomas R <tomas.roun8@gmail.com>
Thu, 3 Aug 2023 05:29:03 +0000 (07:29 +0200)
committerGitHub <noreply@github.com>
Thu, 3 Aug 2023 05:29:03 +0000 (10:59 +0530)
Lib/test/test_ctypes/test_functions.py
Misc/NEWS.d/next/Core and Builtins/2023-07-30-14-18-49.gh-issue-107455.Es53l7.rst [new file with mode: 0644]
Modules/_ctypes/_ctypes.c

index 9cf680f16620acc482ae11b6f407f6df8c289d03..08eecbc9ea4442ff82a2a8605d2a2deb426cbb68 100644 (file)
@@ -4,8 +4,8 @@ import sys
 import unittest
 from ctypes import (CDLL, Structure, Array, CFUNCTYPE,
                     byref, POINTER, pointer, ArgumentError,
-                    c_char, c_wchar, c_byte, c_char_p,
-                    c_short, c_int, c_long, c_longlong,
+                    c_char, c_wchar, c_byte, c_char_p, c_wchar_p,
+                    c_short, c_int, c_long, c_longlong, c_void_p,
                     c_float, c_double, c_longdouble)
 from _ctypes import _Pointer,  _SimpleCData
 
@@ -92,6 +92,54 @@ class FunctionTestCase(unittest.TestCase):
                          "argument 2: TypeError: one character unicode string "
                          "expected")
 
+    def test_c_char_p_parm(self):
+        """Test the error message when converting an incompatible type to c_char_p."""
+        proto = CFUNCTYPE(c_int, c_char_p)
+        def callback(*args):
+            return 0
+
+        callback = proto(callback)
+        self.assertEqual(callback(b"abc"), 0)
+
+        with self.assertRaises(ArgumentError) as cm:
+            callback(10)
+
+        self.assertEqual(str(cm.exception),
+                         "argument 1: TypeError: 'int' object cannot be "
+                         "interpreted as ctypes.c_char_p")
+
+    def test_c_wchar_p_parm(self):
+        """Test the error message when converting an incompatible type to c_wchar_p."""
+        proto = CFUNCTYPE(c_int, c_wchar_p)
+        def callback(*args):
+            return 0
+
+        callback = proto(callback)
+        self.assertEqual(callback("abc"), 0)
+
+        with self.assertRaises(ArgumentError) as cm:
+            callback(10)
+
+        self.assertEqual(str(cm.exception),
+                         "argument 1: TypeError: 'int' object cannot be "
+                         "interpreted as ctypes.c_wchar_p")
+
+    def test_c_void_p_parm(self):
+        """Test the error message when converting an incompatible type to c_void_p."""
+        proto = CFUNCTYPE(c_int, c_void_p)
+        def callback(*args):
+            return 0
+
+        callback = proto(callback)
+        self.assertEqual(callback(5), 0)
+
+        with self.assertRaises(ArgumentError) as cm:
+            callback(2.5)
+
+        self.assertEqual(str(cm.exception),
+                         "argument 1: TypeError: 'float' object cannot be "
+                         "interpreted as ctypes.c_void_p")
+
     def test_wchar_result(self):
         f = dll._testfunc_i_bhilfd
         f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-30-14-18-49.gh-issue-107455.Es53l7.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-30-14-18-49.gh-issue-107455.Es53l7.rst
new file mode 100644 (file)
index 0000000..84a9325
--- /dev/null
@@ -0,0 +1,3 @@
+Improve error messages when converting an incompatible type to
+:class:`ctypes.c_char_p`, :class:`ctypes.c_wchar_p` and
+:class:`ctypes.c_void_p`.
index 8d4fd30150f19cc0b858715f83cb3119b9ff17d4..9aee37a9d954ef4db21c17b2d4b1e1b5cf96a9fe 100644 (file)
@@ -1728,9 +1728,9 @@ c_wchar_p_from_param(PyObject *type, PyObject *value)
         Py_DECREF(as_parameter);
         return value;
     }
-    /* XXX better message */
-    PyErr_SetString(PyExc_TypeError,
-                    "wrong type");
+    PyErr_Format(PyExc_TypeError,
+                 "'%.200s' object cannot be interpreted "
+                 "as ctypes.c_wchar_p", Py_TYPE(value)->tp_name);
     return NULL;
 }
 
@@ -1792,9 +1792,9 @@ c_char_p_from_param(PyObject *type, PyObject *value)
         Py_DECREF(as_parameter);
         return value;
     }
-    /* XXX better message */
-    PyErr_SetString(PyExc_TypeError,
-                    "wrong type");
+    PyErr_Format(PyExc_TypeError,
+                 "'%.200s' object cannot be interpreted "
+                 "as ctypes.c_char_p", Py_TYPE(value)->tp_name);
     return NULL;
 }
 
@@ -1927,9 +1927,9 @@ c_void_p_from_param(PyObject *type, PyObject *value)
         Py_DECREF(as_parameter);
         return value;
     }
-    /* XXX better message */
-    PyErr_SetString(PyExc_TypeError,
-                    "wrong type");
+    PyErr_Format(PyExc_TypeError,
+                 "'%.200s' object cannot be interpreted "
+                 "as ctypes.c_void_p", Py_TYPE(value)->tp_name);
     return NULL;
 }