Author: Armin Rigo <[email protected]>
Branch: verifier2
Changeset: r725:5fbd86edc101
Date: 2012-07-27 17:18 +0200
http://bitbucket.org/cffi/cffi/changeset/5fbd86edc101/
Log: hg merge default
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -3105,7 +3105,7 @@
/* then enough room for the result --- which means at least
sizeof(ffi_arg), according to the ffi docs */
i = fb->rtype->size;
- if (i < sizeof(ffi_arg))
+ if (i < (Py_ssize_t)sizeof(ffi_arg))
i = sizeof(ffi_arg);
exchange_offset += i;
}
@@ -3361,7 +3361,17 @@
/* work work work around a libffi irregularity: for integer return
types we have to fill at least a complete 'ffi_arg'-sized result
buffer. */
- if (ctype->ct_size < sizeof(ffi_arg)) {
+ if (ctype->ct_size < (Py_ssize_t)sizeof(ffi_arg)) {
+ if (ctype->ct_flags & CT_VOID) {
+ if (pyobj == Py_None) {
+ return 0;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "callback with the return type 'void' must return None");
+ return -1;
+ }
+ }
if ((ctype->ct_flags & (CT_PRIMITIVE_SIGNED | CT_IS_ENUM))
== CT_PRIMITIVE_SIGNED) {
PY_LONG_LONG value;
@@ -3429,16 +3439,8 @@
py_res = PyEval_CallObject(py_ob, py_args);
if (py_res == NULL)
goto error;
-
- if (SIGNATURE(1)->ct_size > 0) {
- if (convert_from_object_fficallback(result, SIGNATURE(1), py_res) < 0)
- goto error;
- }
- else if (py_res != Py_None) {
- PyErr_SetString(PyExc_TypeError, "callback with the return type 'void'"
- " must return None");
+ if (convert_from_object_fficallback(result, SIGNATURE(1), py_res) < 0)
goto error;
- }
done:
Py_XDECREF(py_args);
Py_XDECREF(py_res);
@@ -3487,14 +3489,8 @@
ctresult = (CTypeDescrObject *)PyTuple_GET_ITEM(ct->ct_stuff, 1);
size = ctresult->ct_size;
- if (ctresult->ct_flags & (CT_PRIMITIVE_CHAR | CT_PRIMITIVE_SIGNED |
- CT_PRIMITIVE_UNSIGNED)) {
- if (size < sizeof(ffi_arg))
- size = sizeof(ffi_arg);
- }
- else if (size < 0) {
- size = 0;
- }
+ if (size < (Py_ssize_t)sizeof(ffi_arg))
+ size = sizeof(ffi_arg);
py_rawerr = PyString_FromStringAndSize(NULL, size);
if (py_rawerr == NULL)
return NULL;
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -926,6 +926,17 @@
assert s.a == -10
assert s.b == 1E-42
+def test_callback_returning_void():
+ BVoid = new_void_type()
+ BFunc = new_function_type((), BVoid, False)
+ def cb():
+ seen.append(42)
+ f = callback(BFunc, cb)
+ seen = []
+ f()
+ assert seen == [42]
+ py.test.raises(TypeError, callback, BFunc, cb, -42)
+
def test_enum_type():
BEnum = new_enum_type("foo", (), ())
assert repr(BEnum) == "<ctype 'enum foo'>"
diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py
--- a/cffi/backend_ctypes.py
+++ b/cffi/backend_ctypes.py
@@ -817,6 +817,7 @@
return CTypesFunctionPtr
def new_enum_type(self, name, enumerators, enumvalues):
+ assert isinstance(name, str)
mapping = dict(zip(enumerators, enumvalues))
reverse_mapping = dict(reversed(zip(enumvalues, enumerators)))
CTypesInt = self.ffi._get_cached_btype(model.PrimitiveType('int'))
diff --git a/cffi/cparser.py b/cffi/cparser.py
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -383,11 +383,27 @@
"not immediately constant expression")
def _get_enum_type(self, type):
+ # See _get_struct_or_union_type() for the reason of the
+ # complicated logic here. This is still a simplified version,
+ # assuming that it's ok to assume the more complicated cases
+ # don't occur...
+ try:
+ return self._structnode2type[type]
+ except KeyError:
+ pass
name = type.name
+ if name is None:
+ self._anonymous_counter += 1
+ explicit_name = '$%d' % self._anonymous_counter
+ key = None
+ else:
+ explicit_name = name
+ key = 'enum %s' % (name,)
+ tp = self._declarations.get(key, None)
+ if tp is not None:
+ return tp
+ #
decls = type.values
- key = 'enum %s' % (name,)
- if key in self._declarations:
- return self._declarations[key]
if decls is not None:
enumerators = [enum.name for enum in decls.enumerators]
partial = False
@@ -403,11 +419,13 @@
enumvalues.append(nextenumvalue)
nextenumvalue += 1
enumvalues = tuple(enumvalues)
- tp = model.EnumType(name, enumerators, enumvalues)
+ tp = model.EnumType(explicit_name, enumerators, enumvalues)
tp.partial = partial
- self._declare(key, tp)
+ if key is not None:
+ self._declare(key, tp)
else: # opaque enum
enumerators = ()
enumvalues = ()
- tp = model.EnumType(name, (), ())
+ tp = model.EnumType(explicit_name, (), ())
+ self._structnode2type[type] = tp
return tp
diff --git a/doc/source/index.rst b/doc/source/index.rst
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -79,6 +79,10 @@
* a C compiler is required to use CFFI during development, but not to run
correctly-installed programs that use CFFI.
+* `py.test`_ is needed to run the tests of CFFI.
+
+.. _`py.test`: http://pypi.python.org/pypi/pytest
+
Download and Installation:
* https://bitbucket.org/cffi/cffi/downloads
diff --git a/testing/backend_tests.py b/testing/backend_tests.py
--- a/testing/backend_tests.py
+++ b/testing/backend_tests.py
@@ -1179,3 +1179,11 @@
assert ffi1.typeof("enum foo") is not ffi2.typeof("enum foo")
# sanity check: twice 'ffi1'
assert ffi1.typeof("struct foo*") is ffi1.typeof("struct foo *")
+
+ def test_anonymous_enum(self):
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("typedef enum { Value0 = 0 } e, *pe;\n"
+ "typedef enum { Value1 = 1 } e1;")
+ assert ffi.getctype("e*") == 'enum $1 *'
+ assert ffi.getctype("pe") == 'enum $1 *'
+ assert ffi.getctype("e1*") == 'enum $2 *'
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit