Author: Armin Rigo <[email protected]>
Branch: static-callback
Changeset: r2415:4a750b4d4bfa
Date: 2015-11-18 10:00 +0100
http://bitbucket.org/cffi/cffi/changeset/4a750b4d4bfa/
Log: update the code to use 'extern "Python"'
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -6350,8 +6350,8 @@
}
#endif
-struct _cffi_callpy_s; /* forward declaration */
-static void _cffi_call_python(struct _cffi_callpy_s *callpy, char *args);
+struct _cffi_externpy_s; /* forward declaration */
+static void _cffi_call_python(struct _cffi_externpy_s *, char *args);
static void *cffi_exports[] = {
NULL,
diff --git a/c/call_python.c b/c/call_python.c
--- a/c/call_python.c
+++ b/c/call_python.c
@@ -1,5 +1,5 @@
-static PyObject *_ffi_call_python_decorator(PyObject *outer_args, PyObject *fn)
+static PyObject *_ffi_def_extern_decorator(PyObject *outer_args, PyObject *fn)
{
#if PY_MAJOR_VERSION >= 3
# error review!
@@ -8,7 +8,7 @@
PyObject *error, *onerror, *infotuple, *x;
int index;
const struct _cffi_global_s *g;
- struct _cffi_callpy_s *callpy;
+ struct _cffi_externpy_s *externpy;
CTypeDescrObject *ct;
FFIObject *ffi;
builder_c_t *types_builder;
@@ -33,7 +33,7 @@
if (index < 0)
goto not_found;
g = &types_builder->ctx.globals[index];
- if (_CFFI_GETOP(g->type_op) != _CFFI_OP_CALL_PYTHON)
+ if (_CFFI_GETOP(g->type_op) != _CFFI_OP_EXTERN_PYTHON)
goto not_found;
Py_XDECREF(name);
@@ -50,9 +50,9 @@
/* attach infotuple to reserved1, where it will stay forever
unless a new version is attached later */
- callpy = (struct _cffi_callpy_s *)g->address;
- x = (PyObject *)callpy->reserved1;
- callpy->reserved1 = (void *)infotuple;
+ externpy = (struct _cffi_externpy_s *)g->address;
+ x = (PyObject *)externpy->reserved1;
+ externpy->reserved1 = (void *)infotuple;
Py_XDECREF(x);
/* return a cdata of type function-pointer, equal to the one
@@ -62,22 +62,22 @@
return x;
not_found:
- PyErr_Format(FFIError, "ffi.call_python('%s'): name not found as a "
- "CFFI_CALL_PYTHON line from the cdef", s);
+ PyErr_Format(FFIError, "ffi.def_extern('%s'): no 'extern \"Python\"' "
+ "function with this name", s);
Py_XDECREF(name);
return NULL;
}
-static void _cffi_call_python(struct _cffi_callpy_s *callpy, char *args)
+static void _cffi_call_python(struct _cffi_externpy_s *externpy, char *args)
{
- /* Invoked by the helpers generated from CFFI_CALL_PYTHON in the cdef.
+ /* Invoked by the helpers generated from extern "Python" in the cdef.
- 'callpy' is a static structure that describes which of the
- CFFI_CALL_PYTHON is called. It has got fields 'name' and
+ 'externpy' is a static structure that describes which of the
+ extern "Python" functions is called. It has got fields 'name' and
'type_index' describing the function, and more reserved fields
that are initially zero. These reserved fields are set up by
- ffi.call_python(), which invokes init_call_python() below.
+ ffi.def_extern(), which invokes _ffi_def_extern_decorator() above.
'args' is a pointer to an array of 8-byte entries. Each entry
contains an argument. If an argument is less than 8 bytes, only
@@ -85,8 +85,9 @@
argument is 'long double' or a struct/union, then it is passed
by reference.
- 'args' is also used as the place to write the result to. In all
- cases, 'args' is at least 8 bytes in size.
+ 'args' is also used as the place to write the result to
+ (directly, even if more than 8 bytes). In all cases, 'args' is
+ at least 8 bytes in size.
*/
save_errno();
{
@@ -94,21 +95,20 @@
PyGILState_STATE state = PyGILState_Ensure();
#endif
- if (callpy->reserved1 == NULL) {
+ if (externpy->reserved1 == NULL) {
/* not initialized! */
PyObject *f = PySys_GetObject("stderr");
if (f != NULL) {
- PyFile_WriteString("CFFI_CALL_PYTHON: function ", f);
- PyFile_WriteString(callpy->name, f);
+ PyFile_WriteString("extern \"Python\": function ", f);
+ PyFile_WriteString(externpy->name, f);
PyFile_WriteString("() called, but no code was attached "
- "to it yet with ffi.call_python('", f);
- PyFile_WriteString(callpy->name, f);
- PyFile_WriteString("'). Returning 0.\n", f);
+ "to it yet with @ffi.def_extern(). "
+ "Returning 0.\n", f);
}
- memset(args, 0, callpy->size_of_result);
+ memset(args, 0, externpy->size_of_result);
}
else {
- general_invoke_callback(0, args, args, callpy->reserved1);
+ general_invoke_callback(0, args, args, externpy->reserved1);
}
#ifdef WITH_THREAD
diff --git a/c/cffi1_module.c b/c/cffi1_module.c
--- a/c/cffi1_module.c
+++ b/c/cffi1_module.c
@@ -174,7 +174,7 @@
/* initialize the exports array */
num_exports = 25;
- if (ctx->flags & 1) /* set to mean "uses _cffi_call_python" */
+ if (ctx->flags & 1) /* set to mean that 'extern "Python"' is used */
num_exports = 26;
memcpy(exports, (char *)cffi_exports, num_exports * sizeof(void *));
diff --git a/c/ffi_obj.c b/c/ffi_obj.c
--- a/c/ffi_obj.c
+++ b/c/ffi_obj.c
@@ -744,10 +744,10 @@
#define ffi_gc b_gcp /* ffi_gc() => b_gcp()
from _cffi_backend.c */
-PyDoc_STRVAR(ffi_call_python_doc,
+PyDoc_STRVAR(ffi_def_extern_doc,
"A decorator. Attaches the decorated Python function to the C code\n"
-"generated for the CFFI_CALL_PYTHON function of the same name. Calling\n"
-"the C function will then invoke the Python function.\n"
+"generated for the 'extern \"Python\"' function of the same name.\n"
+"Calling the C function will then invoke the Python function.\n"
"\n"
"Optional arguments: 'name' is the name of the C function, if\n"
"different from the Python function; and 'error' and 'onerror'\n"
@@ -755,13 +755,13 @@
"(see the docs for details).");
/* forward; see call_python.c */
-static PyObject *_ffi_call_python_decorator(PyObject *, PyObject *);
+static PyObject *_ffi_def_extern_decorator(PyObject *, PyObject *);
-static PyObject *ffi_call_python(FFIObject *self, PyObject *args,
- PyObject *kwds)
+static PyObject *ffi_def_extern(FFIObject *self, PyObject *args,
+ PyObject *kwds)
{
- static PyMethodDef md = {"call_python_decorator",
- (PyCFunction)_ffi_call_python_decorator, METH_O};
+ static PyMethodDef md = {"def_extern_decorator",
+ (PyCFunction)_ffi_def_extern_decorator, METH_O};
PyObject *name = Py_None, *error = Py_None;
PyObject *res, *onerror = Py_None;
static char *keywords[] = {"name", "error", "onerror", NULL};
@@ -922,7 +922,7 @@
{"addressof", (PyCFunction)ffi_addressof, METH_VARARGS, ffi_addressof_doc},
{"alignof", (PyCFunction)ffi_alignof, METH_O, ffi_alignof_doc},
{"buffer", (PyCFunction)ffi_buffer, METH_VKW, ffi_buffer_doc},
- {"call_python",(PyCFunction)ffi_call_python,METH_VKW,
ffi_call_python_doc},
+ {"def_extern", (PyCFunction)ffi_def_extern, METH_VKW, ffi_def_extern_doc},
{"callback", (PyCFunction)ffi_callback, METH_VKW, ffi_callback_doc},
{"cast", (PyCFunction)ffi_cast, METH_VARARGS, ffi_cast_doc},
{"dlclose", (PyCFunction)ffi_dlclose, METH_VARARGS, ffi_dlclose_doc},
diff --git a/c/lib_obj.c b/c/lib_obj.c
--- a/c/lib_obj.c
+++ b/c/lib_obj.c
@@ -364,8 +364,8 @@
break;
}
- case _CFFI_OP_CALL_PYTHON:
- /* for reading 'lib.bar' where bar is declared with CFFI_CALL_PYTHON */
+ case _CFFI_OP_EXTERN_PYTHON:
+ /* for reading 'lib.bar' where bar is declared with extern "Python" */
ct = realize_c_type(types_builder, types_builder->ctx.types,
_CFFI_GETARG(g->type_op));
if (ct == NULL)
diff --git a/cffi/_cffi_include.h b/cffi/_cffi_include.h
--- a/cffi/_cffi_include.h
+++ b/cffi/_cffi_include.h
@@ -147,7 +147,7 @@
#define _cffi_convert_array_from_object \
((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24])
#define _cffi_call_python \
- ((void(*)(struct _cffi_callpy_s *, char *))_cffi_exports[25])
+ ((void(*)(struct _cffi_externpy_s *, char *))_cffi_exports[25])
#define _CFFI_NUM_EXPORTS 26
typedef struct _ctypedescr CTypeDescrObject;
@@ -206,7 +206,7 @@
/********** end CPython-specific section **********/
#else
_CFFI_UNUSED_FN
-static void (*_cffi_call_python)(struct _cffi_callpy_s *, char *);
+static void (*_cffi_call_python)(struct _cffi_externpy_s *, char *);
#endif
diff --git a/cffi/parse_c_type.h b/cffi/parse_c_type.h
--- a/cffi/parse_c_type.h
+++ b/cffi/parse_c_type.h
@@ -27,7 +27,7 @@
#define _CFFI_OP_DLOPEN_FUNC 35
#define _CFFI_OP_DLOPEN_CONST 37
#define _CFFI_OP_GLOBAL_VAR_F 39
-#define _CFFI_OP_CALL_PYTHON 41
+#define _CFFI_OP_EXTERN_PYTHON 41
#define _CFFI_PRIM_VOID 0
#define _CFFI_PRIM_BOOL 1
@@ -161,7 +161,7 @@
const char *error_message;
};
-struct _cffi_callpy_s {
+struct _cffi_externpy_s {
const char *name;
size_t size_of_result;
void *reserved1, *reserved2;
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -118,7 +118,7 @@
class Recompiler:
- _num_callpy = 0
+ _num_externpy = 0
def __init__(self, ffi, module_name, target_is_python=False):
self.ffi = ffi
@@ -358,8 +358,8 @@
prnt(' NULL, /* no includes */')
prnt(' %d, /* num_types */' % (len(self.cffi_types),))
flags = 0
- if self._num_callpy:
- flags |= 1 # set to mean "uses _cffi_call_python"
+ if self._num_externpy:
+ flags |= 1 # set to mean that we use extern "Python"
prnt(' %d, /* flags */' % flags)
prnt('};')
prnt()
@@ -370,10 +370,11 @@
prnt('PyMODINIT_FUNC')
prnt('_cffi_pypyinit_%s(const void *p[])' % (base_module_name,))
prnt('{')
- prnt(' if (((intptr_t)p[0]) >= 0x0A03) {')
- prnt(' _cffi_call_python = (void(*)(struct _cffi_callpy_s *, '
- 'char *))p[1];')
- prnt(' }')
+ if self._num_externpy:
+ prnt(' if (((intptr_t)p[0]) >= 0x0A03) {')
+ prnt(' _cffi_call_python = '
+ '(void(*)(struct _cffi_externpy_s *, char *))p[1];')
+ prnt(' }')
prnt(' p[0] = (const void *)%s;' % VERSION)
prnt(' p[1] = &_cffi_type_context;')
prnt('}')
@@ -1116,13 +1117,13 @@
GlobalExpr(name, '_cffi_var_%s' % name, CffiOp(op, type_index)))
# ----------
- # CFFI_CALL_PYTHON
+ # extern "Python"
- def _generate_cpy_call_python_collecttype(self, tp, name):
+ def _generate_cpy_extern_python_collecttype(self, tp, name):
assert isinstance(tp, model.FunctionPtrType)
self._do_collect_type(tp)
- def _generate_cpy_call_python_decl(self, tp, name):
+ def _generate_cpy_extern_python_decl(self, tp, name):
prnt = self._prnt
if isinstance(tp.result, model.VoidType):
size_of_result = '0'
@@ -1130,7 +1131,7 @@
context = 'result of %s' % name
size_of_result = '(int)sizeof(%s)' % (
tp.result.get_c_name('', context),)
- prnt('static struct _cffi_callpy_s _cffi_callpy__%s =' % name)
+ prnt('static struct _cffi_externpy_s _cffi_externpy__%s =' % name)
prnt(' { "%s", %s };' % (name, size_of_result))
prnt()
#
@@ -1166,23 +1167,23 @@
arg = '&' + arg
type = model.PointerType(type)
prnt(' *(%s)(p + %d) = %s;' % (type.get_c_name('*'), i*8, arg))
- prnt(' _cffi_call_python(&_cffi_callpy__%s, p);' % name)
+ prnt(' _cffi_call_python(&_cffi_externpy__%s, p);' % name)
if not isinstance(tp.result, model.VoidType):
prnt(' return *(%s)p;' % (tp.result.get_c_name('*'),))
prnt('}')
prnt()
- self._num_callpy += 1
+ self._num_externpy += 1
- def _generate_cpy_call_python_ctx(self, tp, name):
+ def _generate_cpy_extern_python_ctx(self, tp, name):
if self.target_is_python:
raise ffiplatform.VerificationError(
- "cannot use CFFI_CALL_PYTHON in the ABI mode")
+ "cannot use 'extern \"Python\"' in the ABI mode")
if tp.ellipsis:
- raise NotImplementedError("CFFI_CALL_PYTHON with a vararg
function")
+ raise NotImplementedError("a vararg function is extern \"Python\"")
type_index = self._typesdict[tp]
- type_op = CffiOp(OP_CALL_PYTHON, type_index)
+ type_op = CffiOp(OP_EXTERN_PYTHON, type_index)
self._lsts["global"].append(
- GlobalExpr(name, '&_cffi_callpy__%s' % name, type_op, name))
+ GlobalExpr(name, '&_cffi_externpy__%s' % name, type_op, name))
# ----------
# emitting the opcodes for individual types
diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py
--- a/testing/cffi1/test_recompiler.py
+++ b/testing/cffi1/test_recompiler.py
@@ -1494,24 +1494,26 @@
def __exit__(self, *args):
sys.stderr = self.old_stderr
-def test_call_python_1():
+def test_extern_python_1():
ffi = FFI()
ffi.cdef("""
- CFFI_CALL_PYTHON int bar(int, int);
- CFFI_CALL_PYTHON void baz(int, int);
- CFFI_CALL_PYTHON int bok(void);
- CFFI_CALL_PYTHON void boz(void);
+ extern "Python" {
+ int bar(int, int);
+ void baz(int, int);
+ int bok(void);
+ void boz(void);
+ }
""")
- lib = verify(ffi, 'test_call_python_1', "")
+ lib = verify(ffi, 'test_extern_python_1', "")
assert ffi.typeof(lib.bar) == ffi.typeof("int(*)(int, int)")
with StdErrCapture() as f:
res = lib.bar(4, 5)
assert res == 0
assert f.getvalue() == (
- "CFFI_CALL_PYTHON: function bar() called, but no code was attached "
- "to it yet with ffi.call_python('bar'). Returning 0.\n")
+ "extern \"Python\": function bar() called, but no code was attached "
+ "to it yet with @ffi.def_extern(). Returning 0.\n")
- @ffi.call_python("bar")
+ @ffi.def_extern("bar")
def my_bar(x, y):
seen.append(("Bar", x, y))
return x * y
@@ -1521,7 +1523,7 @@
assert seen == [("Bar", 6, 7)]
assert res == 42
- @ffi.call_python()
+ @ffi.def_extern()
def baz(x, y):
seen.append(("Baz", x, y))
seen = []
@@ -1531,53 +1533,53 @@
assert type(seen[0][1]) is type(seen[0][2]) is int
assert baz == lib.baz
- @ffi.call_python(name="bok")
- def bok():
+ @ffi.def_extern(name="bok")
+ def bokk():
seen.append("Bok")
return 42
seen = []
- assert lib.bok() == bok() == 42
+ assert lib.bok() == bokk() == 42
assert seen == ["Bok", "Bok"]
- @ffi.call_python()
+ @ffi.def_extern()
def boz():
seen.append("Boz")
seen = []
assert lib.boz() is boz() is None
assert seen == ["Boz", "Boz"]
-def test_call_python_bogus_name():
+def test_extern_python_bogus_name():
ffi = FFI()
ffi.cdef("int abc;")
- lib = verify(ffi, 'test_call_python_bogus_name', "int abc;")
+ lib = verify(ffi, 'test_extern_python_bogus_name', "int abc;")
def fn():
pass
- py.test.raises(ffi.error, ffi.call_python("unknown_name"), fn)
- py.test.raises(ffi.error, ffi.call_python("abc"), fn)
+ py.test.raises(ffi.error, ffi.def_extern("unknown_name"), fn)
+ py.test.raises(ffi.error, ffi.def_extern("abc"), fn)
assert lib.abc == 0
- e = py.test.raises(ffi.error, ffi.call_python("abc"), fn)
- assert str(e.value) == ("ffi.call_python('abc'): name not found as a "
- "CFFI_CALL_PYTHON line from the cdef")
- e = py.test.raises(ffi.error, ffi.call_python(), fn)
- assert str(e.value) == ("ffi.call_python('fn'): name not found as a "
- "CFFI_CALL_PYTHON line from the cdef")
+ e = py.test.raises(ffi.error, ffi.def_extern("abc"), fn)
+ assert str(e.value) == ("ffi.def_extern('abc'): no 'extern \"Python\"' "
+ "function with this name")
+ e = py.test.raises(ffi.error, ffi.def_extern(), fn)
+ assert str(e.value) == ("ffi.def_extern('fn'): no 'extern \"Python\"' "
+ "function with this name")
#
- py.test.raises(TypeError, ffi.call_python(42), fn)
- py.test.raises((TypeError, AttributeError), ffi.call_python(), "foo")
+ py.test.raises(TypeError, ffi.def_extern(42), fn)
+ py.test.raises((TypeError, AttributeError), ffi.def_extern(), "foo")
class X:
pass
x = X()
x.__name__ = x
- py.test.raises(TypeError, ffi.call_python(), x)
+ py.test.raises(TypeError, ffi.def_extern(), x)
-def test_call_python_bogus_result_type():
+def test_extern_python_bogus_result_type():
ffi = FFI()
- ffi.cdef("CFFI_CALL_PYTHON void bar(int);")
- lib = verify(ffi, 'test_call_python_bogus_result_type', "")
+ ffi.cdef("""extern "Python" void bar(int);""")
+ lib = verify(ffi, 'test_extern_python_bogus_result_type', "")
#
def bar(n):
return n * 10
- bar1 = ffi.call_python()(bar)
+ bar1 = ffi.def_extern()(bar)
with StdErrCapture() as f:
res = bar1(321)
assert res is None
@@ -1586,39 +1588,39 @@
"Trying to convert the result back to C:\n"
"TypeError: callback with the return type 'void' must return None\n")
-def test_call_python_redefine():
+def test_extern_python_redefine():
ffi = FFI()
- ffi.cdef("CFFI_CALL_PYTHON int bar(int);")
- lib = verify(ffi, 'test_call_python_redefine', "")
+ ffi.cdef("""extern "Python" int bar(int);""")
+ lib = verify(ffi, 'test_extern_python_redefine', "")
#
- @ffi.call_python()
+ @ffi.def_extern()
def bar(n):
return n * 10
assert lib.bar(42) == 420
#
- @ffi.call_python()
+ @ffi.def_extern()
def bar(n):
return -n
assert lib.bar(42) == -42
-def test_call_python_struct():
+def test_extern_python_struct():
ffi = FFI()
ffi.cdef("""
struct foo_s { int a, b, c; };
- CFFI_CALL_PYTHON int bar(int, struct foo_s, int);
- CFFI_CALL_PYTHON struct foo_s baz(int, int);
- CFFI_CALL_PYTHON struct foo_s bok(void);
+ extern "Python" int bar(int, struct foo_s, int);
+ extern "Python" { struct foo_s baz(int, int);
+ struct foo_s bok(void); }
""")
- lib = verify(ffi, 'test_call_python_struct',
+ lib = verify(ffi, 'test_extern_python_struct',
"struct foo_s { int a, b, c; };")
#
- @ffi.call_python()
+ @ffi.def_extern()
def bar(x, s, z):
return x + s.a + s.b + s.c + z
res = lib.bar(1000, [1001, 1002, 1004], 1008)
assert res == 5015
#
- @ffi.call_python()
+ @ffi.def_extern()
def baz(x, y):
return [x + y, x - y, x * y]
res = lib.baz(1000, 42)
@@ -1626,22 +1628,22 @@
assert res.b == 958
assert res.c == 42000
#
- @ffi.call_python()
+ @ffi.def_extern()
def bok():
return [10, 20, 30]
res = lib.bok()
assert [res.a, res.b, res.c] == [10, 20, 30]
-def test_call_python_long_double():
+def test_extern_python_long_double():
ffi = FFI()
ffi.cdef("""
- CFFI_CALL_PYTHON int bar(int, long double, int);
- CFFI_CALL_PYTHON long double baz(int, int);
- CFFI_CALL_PYTHON long double bok(void);
+ extern "Python" int bar(int, long double, int);
+ extern "Python" long double baz(int, int);
+ extern "Python" long double bok(void);
""")
- lib = verify(ffi, 'test_call_python_long_double', "")
+ lib = verify(ffi, 'test_extern_python_long_double', "")
#
- @ffi.call_python()
+ @ffi.def_extern()
def bar(x, l, z):
seen.append((x, l, z))
return 6
@@ -1650,42 +1652,42 @@
expected = ffi.cast("long double", 3.5)
assert repr(seen) == repr([(10, expected, 20)])
#
- @ffi.call_python()
+ @ffi.def_extern()
def baz(x, z):
assert x == 10 and z == 20
return expected
res = lib.baz(10, 20)
assert repr(res) == repr(expected)
#
- @ffi.call_python()
+ @ffi.def_extern()
def bok():
return expected
res = lib.bok()
assert repr(res) == repr(expected)
-def test_call_python_signature():
+def test_extern_python_signature():
ffi = FFI()
- lib = verify(ffi, 'test_call_python_signature', "")
- py.test.raises(TypeError, ffi.call_python(425), None)
- py.test.raises(TypeError, ffi.call_python, 'a', 'b', 'c', 'd')
+ lib = verify(ffi, 'test_extern_python_signature', "")
+ py.test.raises(TypeError, ffi.def_extern(425), None)
+ py.test.raises(TypeError, ffi.def_extern, 'a', 'b', 'c', 'd')
-def test_call_python_errors():
+def test_extern_python_errors():
ffi = FFI()
ffi.cdef("""
- CFFI_CALL_PYTHON int bar(int);
+ extern "Python" int bar(int);
""")
- lib = verify(ffi, 'test_call_python_errors', "")
+ lib = verify(ffi, 'test_extern_python_errors', "")
seen = []
def oops(*args):
seen.append(args)
- @ffi.call_python(onerror=oops)
+ @ffi.def_extern(onerror=oops)
def bar(x):
return x + ""
assert bar(10) == 0
- @ffi.call_python(name="bar", onerror=oops, error=-66)
+ @ffi.def_extern(name="bar", onerror=oops, error=-66)
def bar2(x):
return x + ""
assert bar(10) == -66
@@ -1701,5 +1703,5 @@
assert tb.tb_frame.f_code.co_name == "bar2"
#
# a case where 'onerror' is not callable
- py.test.raises(TypeError, ffi.call_python(name='bar', onerror=42),
+ py.test.raises(TypeError, ffi.def_extern(name='bar', onerror=42),
lambda x: x)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit