Author: Armin Rigo <[email protected]>
Branch: cffi-1.0
Changeset: r1757:d683086b3771
Date: 2015-04-18 17:09 +0200
http://bitbucket.org/cffi/cffi/changeset/d683086b3771/
Log: typeof(built-in method of lib object)
diff --git a/new/ffi_obj.c b/new/ffi_obj.c
--- a/new/ffi_obj.c
+++ b/new/ffi_obj.c
@@ -195,14 +195,16 @@
"corresponding <ctype> object.\n"
"It can also be used on 'cdata' instance to get its C type.");
+static PyObject *_cpyextfunc_type_index(PyObject *x); /* forward */
+
static PyObject *ffi_typeof(FFIObject *self, PyObject *arg)
{
PyObject *x = (PyObject *)_ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CDATA);
if (x != NULL) {
Py_INCREF(x);
}
- else if (PyCFunction_Check(arg)) {
- abort(); // XXX
+ else {
+ x = _cpyextfunc_type_index(arg);
}
return x;
}
diff --git a/new/lib_obj.c b/new/lib_obj.c
--- a/new/lib_obj.c
+++ b/new/lib_obj.c
@@ -13,10 +13,11 @@
struct CPyExtFunc_s {
PyMethodDef md;
- builder_c_t *types_builder;
int type_index;
};
+#define METH_CPYEXTFUNC 0x40000000
+
struct LibObject_s {
PyObject_HEAD
builder_c_t *l_types_builder; /* same as the one on the ffi object */
@@ -26,6 +27,38 @@
#define LibObject_Check(ob) ((Py_TYPE(ob) == &Lib_Type))
+static PyObject *_cpyextfunc_type_index(PyObject *x)
+{
+ assert(PyErr_Occurred());
+
+ if (!PyCFunction_Check(x))
+ return NULL;
+ if (!LibObject_Check(PyCFunction_GET_SELF(x)))
+ return NULL;
+ if (!(PyCFunction_GET_FLAGS(x) & METH_CPYEXTFUNC))
+ return NULL;
+
+ PyErr_Clear();
+
+ LibObject *lib = (LibObject *)PyCFunction_GET_SELF(x);
+ struct CPyExtFunc_s *exf;
+ PyObject *tuple, *result;
+
+ exf = (struct CPyExtFunc_s *)(((PyCFunctionObject *)x) -> m_ml);
+ tuple = _realize_c_type_or_func(lib->l_types_builder,
+ lib->l_types_builder->ctx.types,
+ exf->type_index);
+ if (tuple == NULL)
+ return NULL;
+
+ /* 'tuple' is a tuple of length 1 containing the real CT_FUNCTIONPTR
+ object */
+ result = PyTuple_GetItem(tuple, 0);
+ Py_XINCREF(result);
+ Py_DECREF(tuple);
+ return result;
+}
+
static void lib_dealloc(LibObject *lib)
{
Py_DECREF(lib->l_dict);
@@ -79,16 +112,15 @@
goto no_memory;
xfunc->md.ml_meth = (PyCFunction)g->address;
- xfunc->md.ml_flags = flags;
+ xfunc->md.ml_flags = flags | METH_CPYEXTFUNC;
xfunc->md.ml_name = g->name;
/*xfunc->md.ml_doc = ... */
if (xfunc->md.ml_name == NULL)
goto no_memory;
- xfunc->types_builder = lib->l_types_builder;
xfunc->type_index = type_index;
- return PyCFunction_NewEx(&xfunc->md, NULL, lib->l_libname);
+ return PyCFunction_NewEx(&xfunc->md, (PyObject *)lib, lib->l_libname);
no_memory:
PyErr_NoMemory();
diff --git a/new/test_recompiler.py b/new/test_recompiler.py
--- a/new/test_recompiler.py
+++ b/new/test_recompiler.py
@@ -271,3 +271,13 @@
assert ffi.sizeof("struct foo_s") == 4
p = ffi.new("struct foo_s *", [5, [10, 20, 30]])
assert p.a[2] == 30
+
+def test_math_sin_type():
+ ffi = FFI()
+ ffi.cdef("double sin(double);")
+ lib = verify(ffi, 'test_math_sin_type', '#include <math.h>')
+ # 'lib.sin' is typed as a <built-in method> object on lib
+ assert ffi.typeof(lib.sin).cname == "double(*)(double)"
+ # 'x' is another <built-in method> object on lib, made very indirectly
+ x = type(lib).__dir__.__get__(lib)
+ py.test.raises(TypeError, ffi.typeof, x)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit