[pypy-commit] cffi default: Tweak the API with respect to None: it no longer means "NULL".
arigo
noreply at buildbot.pypy.org
Tue Jun 26 10:02:40 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r514:9824c8551f0d
Date: 2012-06-25 23:35 +0200
http://bitbucket.org/cffi/cffi/changeset/9824c8551f0d/
Log: Tweak the API with respect to None: it no longer means "NULL".
diff --git a/c/_ffi_backend.c b/c/_ffi_backend.c
--- a/c/_ffi_backend.c
+++ b/c/_ffi_backend.c
@@ -550,13 +550,7 @@
/* non-primitive types (check done just for performance) */
if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR)) {
char *ptrdata = *(char **)data;
- if (ptrdata != NULL) {
- return new_simple_cdata(ptrdata, ct);
- }
- else {
- Py_INCREF(Py_None);
- return Py_None;
- }
+ return new_simple_cdata(ptrdata, ct);
}
else if (ct->ct_flags & CT_IS_OPAQUE) {
PyErr_Format(PyExc_TypeError, "cannot return a cdata '%s'",
@@ -759,21 +753,17 @@
char *ptrdata;
CTypeDescrObject *ctinit;
- if (init != Py_None) {
- expected = "compatible pointer";
- if (!CData_Check(init))
- goto cannot_convert;
- ctinit = ((CDataObject *)init)->c_type;
- if (!(ctinit->ct_flags & (CT_POINTER|CT_FUNCTIONPTR|CT_ARRAY)))
- goto cannot_convert;
- if (ctinit->ct_itemdescr != ct->ct_itemdescr &&
- !(ct->ct_itemdescr->ct_flags & CT_CAST_ANYTHING))
- goto cannot_convert;
- ptrdata = ((CDataObject *)init)->c_data;
- }
- else {
- ptrdata = NULL;
- }
+ expected = "compatible pointer";
+ if (!CData_Check(init))
+ goto cannot_convert;
+ ctinit = ((CDataObject *)init)->c_type;
+ if (!(ctinit->ct_flags & (CT_POINTER|CT_FUNCTIONPTR|CT_ARRAY)))
+ goto cannot_convert;
+ if (ctinit->ct_itemdescr != ct->ct_itemdescr &&
+ !(ct->ct_itemdescr->ct_flags & CT_CAST_ANYTHING))
+ goto cannot_convert;
+ ptrdata = ((CDataObject *)init)->c_data;
+
*(char **)data = ptrdata;
return 0;
}
@@ -1027,7 +1017,32 @@
static PyObject *cdata_repr(CDataObject *cd)
{
- return PyString_FromFormat("<cdata '%s'>", cd->c_type->ct_name);
+ char *p;
+ PyObject *result, *s = NULL;
+
+ if (cd->c_type->ct_flags & CT_PRIMITIVE_ANY) {
+ PyObject *o = convert_to_object(cd->c_data, cd->c_type);
+ if (o == NULL)
+ return NULL;
+ s = PyObject_Repr(o);
+ Py_DECREF(o);
+ if (s == NULL)
+ return NULL;
+ p = PyString_AS_STRING(s);
+ }
+ else {
+ if (cd->c_data != NULL) {
+ s = PyString_FromFormat("%p", cd->c_data);
+ if (s == NULL)
+ return NULL;
+ p = PyString_AS_STRING(s);
+ }
+ else
+ p = "NULL";
+ }
+ result = PyString_FromFormat("<cdata '%s' %s>", cd->c_type->ct_name, p);
+ Py_XDECREF(s);
+ return result;
}
static PyObject *cdata_str(CDataObject *cd)
@@ -1145,30 +1160,21 @@
static PyObject *cdata_richcompare(PyObject *v, PyObject *w, int op)
{
- int res, full_order;
+ int res;
PyObject *pyres;
char *v_cdata, *w_cdata;
- full_order = (op != Py_EQ && op != Py_NE);
-
assert(CData_Check(v));
+ if (!CData_Check(w))
+ goto Unimplemented;
+
v_cdata = ((CDataObject *)v)->c_data;
- if (full_order &&
- (((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY))
+ w_cdata = ((CDataObject *)w)->c_data;
+ if ((op != Py_EQ && op != Py_NE) &&
+ ((((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY) ||
+ (((CDataObject *)w)->c_type->ct_flags & CT_PRIMITIVE_ANY)))
goto Error;
- if (w == Py_None) {
- w_cdata = NULL;
- }
- else if (CData_Check(w)) {
- w_cdata = ((CDataObject *)w)->c_data;
- if (full_order &&
- (((CDataObject *)w)->c_type->ct_flags & CT_PRIMITIVE_ANY))
- goto Error;
- }
- else
- goto Unimplemented;
-
switch (op) {
case Py_EQ: res = (v_cdata == w_cdata); break;
case Py_NE: res = (v_cdata != w_cdata); break;
@@ -1735,9 +1741,9 @@
{
CTypeDescrObject *ct, *ctitem;
CDataObject_own_base *cdb;
- PyObject *init;
+ PyObject *init = Py_None;
Py_ssize_t dataoffset, datasize, explicitlength;
- if (!PyArg_ParseTuple(args, "O!O:newp", &CTypeDescr_Type, &ct, &init))
+ if (!PyArg_ParseTuple(args, "O!|O:newp", &CTypeDescr_Type, &ct, &init))
return NULL;
explicitlength = -1;
@@ -1854,9 +1860,6 @@
value = (unsigned char)PyString_AS_STRING(ob)[0];
}
}
- else if (ob == Py_None) {
- value = 0;
- }
else {
value = _my_PyLong_AsUnsignedLongLong(ob, 0);
if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
@@ -1887,14 +1890,9 @@
return new_simple_cdata(cdsrc->c_data, ct);
}
}
- if (ob == Py_None) {
- value = 0;
- }
- else {
- value = _my_PyLong_AsUnsignedLongLong(ob, 0);
- if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
- return NULL;
- }
+ value = _my_PyLong_AsUnsignedLongLong(ob, 0);
+ if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
+ return NULL;
return new_simple_cdata((char *)(Py_intptr_t)value, ct);
}
else if (ct->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED
@@ -1928,9 +1926,6 @@
}
value = (unsigned char)PyString_AS_STRING(io)[0];
}
- else if (io == Py_None) {
- value = 0.0;
- }
else {
value = PyFloat_AsDouble(io);
}
@@ -3419,9 +3414,6 @@
if (PyString_Check(obj)) {
return PyString_AS_STRING(obj);
}
- if (obj == Py_None) {
- return NULL;
- }
if (CData_Check(obj)) {
return ((CDataObject *)obj)->c_data;
}
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -48,11 +48,11 @@
def test_cast_to_signed_char():
p = new_primitive_type("signed char")
x = cast(p, -65 + 17*256)
- assert repr(x) == "<cdata 'signed char'>"
+ assert repr(x) == "<cdata 'signed char' -65>"
assert repr(type(x)) == "<type '_ffi_backend.CData'>"
assert int(x) == -65
x = cast(p, -66 + (1<<199)*256)
- assert repr(x) == "<cdata 'signed char'>"
+ assert repr(x) == "<cdata 'signed char' -66>"
assert int(x) == -66
assert (x == cast(p, -66)) is False
assert (x != cast(p, -66)) is True
@@ -75,7 +75,7 @@
assert int(cast(p, max)) == max
assert int(cast(p, min - 1)) == max
assert int(cast(p, max + 1)) == min
- assert int(cast(p, None)) == 0
+ py.test.raises(TypeError, cast, p, None)
assert long(cast(p, min - 1)) == max
for name in ['char', 'short', 'int', 'long', 'long long']:
p = new_primitive_type('unsigned ' + name)
@@ -118,7 +118,7 @@
assert repr(float(cast(p, -0.0))) == '-0.0'
assert float(cast(p, '\x09')) == 9.0
assert float(cast(p, True)) == 1.0
- assert float(cast(p, None)) == 0.0
+ py.test.raises(TypeError, cast, p, None)
def test_character_type():
p = new_primitive_type("char")
@@ -142,22 +142,23 @@
def test_pointer_to_int():
BInt = new_primitive_type("int")
+ py.test.raises(TypeError, newp, BInt)
py.test.raises(TypeError, newp, BInt, None)
BPtr = new_pointer_type(BInt)
+ p = newp(BPtr)
+ assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int()
p = newp(BPtr, None)
assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int()
p = newp(BPtr, 5000)
assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int()
q = cast(BPtr, p)
- assert repr(q) == "<cdata 'int *'>"
+ assert repr(q).startswith("<cdata 'int *' 0x")
assert p == q
assert hash(p) == hash(q)
def test_pointer_bool():
BInt = new_primitive_type("int")
BPtr = new_pointer_type(BInt)
- p = cast(BPtr, None)
- assert bool(p) is False
p = cast(BPtr, 0)
assert bool(p) is False
p = cast(BPtr, 42)
@@ -232,6 +233,29 @@
assert str(cast(BChar, 'A')) == 'A'
py.test.raises(TypeError, cast, BChar, 'foo')
+def test_reading_pointer_to_pointer():
+ BVoidP = new_pointer_type(new_void_type())
+ BCharP = new_pointer_type(new_primitive_type("char"))
+ BInt = new_primitive_type("int")
+ BIntPtr = new_pointer_type(BInt)
+ BIntPtrPtr = new_pointer_type(BIntPtr)
+ q = newp(BIntPtr, 42)
+ assert q[0] == 42
+ p = newp(BIntPtrPtr, None)
+ assert p[0] is not None
+ assert p[0] == cast(BVoidP, 0)
+ assert p[0] == cast(BCharP, 0)
+ assert p[0] != None
+ assert repr(p[0]) == "<cdata 'int *' NULL>"
+ p[0] = q
+ assert p[0] != cast(BVoidP, 0)
+ assert p[0] != cast(BCharP, 0)
+ assert p[0][0] == 42
+ q[0] += 1
+ assert p[0][0] == 43
+ p = newp(BIntPtrPtr, q)
+ assert p[0][0] == 43
+
def test_hash_differences():
BChar = new_primitive_type("char")
BInt = new_primitive_type("int")
@@ -375,10 +399,10 @@
a = newp(p2, [range(n, n+5) for n in [100, 200, 300]])
assert repr(a) == "<cdata 'int[3][5]' owning %d bytes>" % (
3*5*size_of_int(),)
- assert repr(a + 0) == "<cdata 'int(*)[5]'>"
- assert repr(a[0]) == "<cdata 'int[5]'>"
- assert repr((a + 0)[0]) == "<cdata 'int[5]'>"
- assert repr(a[0] + 0) == "<cdata 'int *'>"
+ assert repr(a + 0).startswith("<cdata 'int(*)[5]' 0x")
+ assert repr(a[0]).startswith("<cdata 'int[5]' 0x")
+ assert repr((a + 0)[0]).startswith("<cdata 'int[5]' 0x")
+ assert repr(a[0] + 0).startswith("<cdata 'int *' 0x")
assert type(a[0][0]) is int
assert type((a[0] + 0)[0]) is int
@@ -459,12 +483,11 @@
f = cast(BIntP, int(d))
assert f[3] == 43
#
- for null in [0, None]:
- b = cast(BShortP, null)
- assert not b
- c = cast(BIntP, b)
- assert not c
- assert int(cast(BLongLong, c)) == 0
+ b = cast(BShortP, 0)
+ assert not b
+ c = cast(BIntP, b)
+ assert not c
+ assert int(cast(BLongLong, c)) == 0
def test_alignof():
BInt = new_primitive_type("int")
@@ -538,7 +561,7 @@
BInt = new_primitive_type("int")
BStruct = new_struct_type("foo")
BStructPtr = new_pointer_type(BStruct)
- p = cast(BStructPtr, None)
+ p = cast(BStructPtr, 0)
py.test.raises(AttributeError, "p.a1") # opaque
complete_struct_or_union(BStruct, [('a1', BInt, -1),
('a2', BInt, -1)])
@@ -553,6 +576,15 @@
py.test.raises(AttributeError, "p.foobar")
py.test.raises(AttributeError, "s.foobar")
+def test_union_instance():
+ BInt = new_primitive_type("int")
+ BUInt = new_primitive_type("unsigned int")
+ BUnion = new_union_type("bar")
+ complete_struct_or_union(BUnion, [('a1', BInt, -1), ('a2', BUInt, -1)])
+ p = newp(new_pointer_type(BUnion), -42)
+ assert p.a1 == -42
+ assert p.a2 == -42 + (1 << (8*size_of_int()))
+
def test_struct_pointer():
BInt = new_primitive_type("int")
BStruct = new_struct_type("foo")
@@ -566,23 +598,33 @@
assert p.a2 == 123
def test_struct_init_list():
+ BVoidP = new_pointer_type(new_void_type())
BInt = new_primitive_type("int")
BStruct = new_struct_type("foo")
BStructPtr = new_pointer_type(BStruct)
complete_struct_or_union(BStruct, [('a1', BInt, -1),
('a2', BInt, -1),
- ('a3', BInt, -1)])
+ ('a3', BInt, -1),
+ ('p4', new_pointer_type(BInt), -1)])
s = newp(BStructPtr, [123, 456])
assert s.a1 == 123
assert s.a2 == 456
assert s.a3 == 0
+ assert s.p4 == cast(BVoidP, 0)
#
s = newp(BStructPtr, {'a2': 41122, 'a3': -123})
assert s.a1 == 0
assert s.a2 == 41122
assert s.a3 == -123
+ assert s.p4 == cast(BVoidP, 0)
#
py.test.raises(KeyError, newp, BStructPtr, {'foobar': 0})
+ #
+ p = newp(new_pointer_type(BInt), 14141)
+ s = newp(BStructPtr, [12, 34, 56, p])
+ assert s.p4 == p
+ #
+ py.test.raises(TypeError, newp, BStructPtr, [12, 34, 56, None])
def test_array_in_struct():
BInt = new_primitive_type("int")
@@ -591,7 +633,7 @@
complete_struct_or_union(BStruct, [('a1', BArrayInt5, -1)])
s = newp(new_pointer_type(BStruct), [[20, 24, 27, 29, 30]])
assert s.a1[2] == 27
- assert repr(s.a1) == "<cdata 'int[5]'>"
+ assert repr(s.a1).startswith("<cdata 'int[5]' 0x")
def test_offsetof():
BInt = new_primitive_type("int")
@@ -760,8 +802,9 @@
BVoidP = new_pointer_type(new_void_type())
ll = find_and_load_library('c')
stderr = ll.read_variable(BVoidP, "stderr")
- ll.write_variable(BVoidP, "stderr", None)
- assert ll.read_variable(BVoidP, "stderr") is None
+ ll.write_variable(BVoidP, "stderr", cast(BVoidP, 0))
+ assert ll.read_variable(BVoidP, "stderr") is not None
+ assert not ll.read_variable(BVoidP, "stderr")
ll.write_variable(BVoidP, "stderr", stderr)
assert ll.read_variable(BVoidP, "stderr") == stderr
@@ -798,7 +841,7 @@
def test_cast_to_enum():
BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20))
e = cast(BEnum, 0)
- assert repr(e) == "<cdata 'enum foo'>"
+ assert repr(e) == "<cdata 'enum foo' 'def'>"
assert str(e) == 'def'
assert str(cast(BEnum, -20)) == 'ab'
assert str(cast(BEnum, 'c')) == 'c'
@@ -807,6 +850,8 @@
assert int(cast(BEnum, -242 + 2**128)) == -242
assert str(cast(BEnum, -242 + 2**128)) == '#-242'
assert str(cast(BEnum, '#-20')) == 'ab'
+ assert repr(cast(BEnum, '#-20')) == "<cdata 'enum foo' 'ab'>"
+ assert repr(cast(BEnum, '#-21')) == "<cdata 'enum foo' '#-21'>"
def test_enum_in_struct():
BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20))
More information about the pypy-commit
mailing list