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

Reply via email to