[pypy-commit] cffi default: ffi.getcname().
arigo
noreply at buildbot.pypy.org
Mon Jun 18 10:29:11 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r428:72b5198d9b44
Date: 2012-06-18 10:28 +0200
http://bitbucket.org/cffi/cffi/changeset/72b5198d9b44/
Log: ffi.getcname().
diff --git a/c/_ffi_backend.c b/c/_ffi_backend.c
--- a/c/_ffi_backend.c
+++ b/c/_ffi_backend.c
@@ -3201,6 +3201,34 @@
return PyInt_FromSsize_t(cf->cf_offset);
}
+static PyObject *b_getcname(PyObject *self, PyObject *args)
+{
+ CTypeDescrObject *ct;
+ char *replace_with, *p;
+ PyObject *s;
+ Py_ssize_t namelen, replacelen;
+
+ if (!PyArg_ParseTuple(args, "O!s:getcname",
+ &CTypeDescr_Type, &ct, &replace_with))
+ return NULL;
+
+ namelen = strlen(ct->ct_name);
+ replacelen = strlen(replace_with);
+ s = PyString_FromStringAndSize(NULL, namelen + replacelen);
+ if (s == NULL)
+ return NULL;
+
+ p = PyString_AS_STRING(s);
+ memcpy(p, ct->ct_name, ct->ct_name_position);
+ p += ct->ct_name_position;
+ memcpy(p, replace_with, replacelen);
+ p += replacelen;
+ memcpy(p, ct->ct_name + ct->ct_name_position,
+ namelen - ct->ct_name_position);
+
+ return s;
+}
+
static PyObject *b_buffer(PyObject *self, PyObject *args)
{
CDataObject *cd;
@@ -3378,6 +3406,7 @@
{"sizeof", b_sizeof, METH_O},
{"typeof", b_typeof, METH_O},
{"offsetof", b_offsetof, METH_VARARGS},
+ {"getcname", b_getcname, METH_VARARGS},
{"buffer", b_buffer, METH_VARARGS},
{"get_errno", b_get_errno, METH_NOARGS},
{"set_errno", b_set_errno, METH_VARARGS},
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -169,11 +169,32 @@
return self._backend.buffer(cdata, size)
def callback(self, cdecl, python_callable):
+ """Return a callback object. 'cdecl' must name a C function pointer
+ type. The callback invokes the specified 'python_callable'.
+ Important: the callback object must be manually kept alive for as
+ long as the callback may be invoked from the C level.
+ """
if not callable(python_callable):
raise TypeError("the 'python_callable' argument is not callable")
BFunc = self.typeof(cdecl)
return self._backend.callback(BFunc, python_callable)
+ def getctype(self, cdecl, replace_with=''):
+ """Return a string giving the C type 'cdecl', which may be itself
+ a string or a <ctype> object. If 'replace_with' is given, it gives
+ extra text to append (or insert for more complicated C types), like
+ a variable name, or '*' to get actually the C type 'pointer-to-cdecl'.
+ """
+ if isinstance(cdecl, basestring):
+ cdecl = self.typeof(cdecl)
+ replace_with = replace_with.strip()
+ if (replace_with.startswith('*')
+ and '&[' in self._backend.getcname(cdecl, '&')):
+ replace_with = '(%s)' % replace_with
+ elif replace_with and not replace_with[0] in '[(':
+ replace_with = ' ' + replace_with
+ return self._backend.getcname(cdecl, replace_with)
+
def _get_cached_btype(self, type):
try:
BType = self._cached_btypes[type]
diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py
--- a/cffi/backend_ctypes.py
+++ b/cffi/backend_ctypes.py
@@ -816,6 +816,9 @@
typeof = type
+ def getcname(self, BType, replace_with):
+ return BType._get_c_name(replace_with)
+
class CTypesLibrary(object):
diff --git a/doc/source/index.rst b/doc/source/index.rst
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -565,6 +565,13 @@
``ffi.offsetof("C struct type", "fieldname")``: return the offset within
the struct of the given field. Corresponds to ``offsetof()`` in C.
+``ffi.getcname("C type" or <ctype>, ["extra"])``: return the string
+representation of the given C type. If non-empty, the "extra" string is
+appended (or inserted at the right place in more complicated cases); it
+can be the name of a variable to declare, or an extra part of the type
+like ``"*"`` or ``"[5]"``, so that for example
+``ffi.getcname(ffi.typeof(x), "*")`` returns the string representation
+of the C type "pointer to the same type than x".
Comments and bugs
diff --git a/testing/backend_tests.py b/testing/backend_tests.py
--- a/testing/backend_tests.py
+++ b/testing/backend_tests.py
@@ -845,3 +845,20 @@
assert p.len == 0
assert p.data[9] == 0
py.test.raises(IndexError, "p.data[10]")
+
+ def test_ffi_typeof_getcname(self):
+ ffi = FFI(backend=self.Backend())
+ assert ffi.getctype("int") == "int"
+ assert ffi.getctype("int", 'x') == "int x"
+ assert ffi.getctype("int*") == "int *"
+ assert ffi.getctype("int*", '') == "int *"
+ assert ffi.getctype("int", '*') == "int *"
+ assert ffi.getctype("int", ' * x ') == "int * x"
+ assert ffi.getctype(ffi.typeof("int*"), '*') == "int * *"
+ assert ffi.getctype("int", '[5]') == "int[5]"
+ assert ffi.getctype("int[5]", '[6]') == "int[6][5]"
+ assert ffi.getctype("int[5]", '(*)') == "int(*)[5]"
+ # special-case for convenience: automatically put '()' around '*'
+ assert ffi.getctype("int[5]", '*') == "int(*)[5]"
+ assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]"
+ assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]"
More information about the pypy-commit
mailing list