summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2015-07-09 10:17:21 +0200
committerArmin Rigo <arigo@tunes.org>2015-07-09 10:17:21 +0200
commit0a3a703930232d4046647d756fece564a90ef7cd (patch)
treec2d15d4c8a51f833dd0bfdcdbb59923c0c8bd011
parentedbdf6ea93f08983f4f21d066e697996210c4c38 (diff)
downloadcffi-0a3a703930232d4046647d756fece564a90ef7cd.tar.gz
Issue #213: in case we'd give the error message "initializer for ctype
'A' must be a pointer to same type, not cdata 'B'", but with A=B, then give instead a different error message to try to clear up the confusion
-rw-r--r--c/_cffi_backend.c25
-rw-r--r--c/test_c.py23
2 files changed, 42 insertions, 6 deletions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
index 5c5a52e..ab26098 100644
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -1060,12 +1060,25 @@ static wchar_t _convert_to_wchar_t(PyObject *init)
static int _convert_error(PyObject *init, const char *ct_name,
const char *expected)
{
- if (CData_Check(init))
- PyErr_Format(PyExc_TypeError,
- "initializer for ctype '%s' must be a %s, "
- "not cdata '%s'",
- ct_name, expected,
- ((CDataObject *)init)->c_type->ct_name);
+ if (CData_Check(init)) {
+ const char *ct_name_2 = ((CDataObject *)init)->c_type->ct_name;
+ if (strcmp(ct_name, ct_name_2) != 0)
+ PyErr_Format(PyExc_TypeError,
+ "initializer for ctype '%s' must be a %s, "
+ "not cdata '%s'",
+ ct_name, expected, ct_name_2);
+ else {
+ /* in case we'd give the error message "initializer for
+ ctype 'A' must be a pointer to same type, not cdata
+ 'B'", but with A=B, then give instead a different error
+ message to try to clear up the confusion */
+ PyErr_Format(PyExc_TypeError,
+ "initializer for ctype '%s' appears indeed to be '%s',"
+ " but the types are different (check that you are not"
+ " e.g. mixing up different ffi instances)",
+ ct_name, ct_name_2);
+ }
+ }
else
PyErr_Format(PyExc_TypeError,
"initializer for ctype '%s' must be a %s, "
diff --git a/c/test_c.py b/c/test_c.py
index 59fe157..37dd4a3 100644
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -3413,6 +3413,29 @@ def test_dereference_null_ptr():
py.test.raises(RuntimeError, "p[42]")
py.test.raises(RuntimeError, "p[42] = -1")
+def test_mixup():
+ BStruct1 = new_struct_type("foo")
+ BStruct2 = new_struct_type("foo") # <= same name as BStruct1
+ BStruct3 = new_struct_type("bar")
+ BStruct1Ptr = new_pointer_type(BStruct1)
+ BStruct2Ptr = new_pointer_type(BStruct2)
+ BStruct3Ptr = new_pointer_type(BStruct3)
+ BStruct1PtrPtr = new_pointer_type(BStruct1Ptr)
+ BStruct2PtrPtr = new_pointer_type(BStruct2Ptr)
+ BStruct3PtrPtr = new_pointer_type(BStruct3Ptr)
+ pp1 = newp(BStruct1PtrPtr)
+ pp2 = newp(BStruct2PtrPtr)
+ pp3 = newp(BStruct3PtrPtr)
+ pp1[0] = pp1[0]
+ e = py.test.raises(TypeError, "pp3[0] = pp1[0]")
+ assert str(e.value).startswith("initializer for ctype 'bar *' must be a ")
+ assert str(e.value).endswith(", not cdata 'foo *'")
+ e = py.test.raises(TypeError, "pp2[0] = pp1[0]")
+ assert str(e.value) == ("initializer for ctype 'foo *' appears indeed to "
+ "be 'foo *', but the types are different (check "
+ "that you are not e.g. mixing up different ffi "
+ "instances)")
+
def test_version():
# this test is here mostly for PyPy
assert __version__ == "1.2.0"