[pypy-commit] cffi cpy-extension: _cffi_to_c_char_p(). Use the technique documented in
arigo
noreply at buildbot.pypy.org
Tue Jun 12 16:03:44 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: cpy-extension
Changeset: r289:e210108bc5d9
Date: 2012-06-12 16:03 +0200
http://bitbucket.org/cffi/cffi/changeset/e210108bc5d9/
Log: _cffi_to_c_char_p(). Use the technique documented in
http://docs.python.org/release/2.5.3/ext/using-cobjects.html to
access a function defined in _ffi_backend from the C code in the
generated module _cffi_N.
diff --git a/c/_ffi_backend.c b/c/_ffi_backend.c
--- a/c/_ffi_backend.c
+++ b/c/_ffi_backend.c
@@ -3236,6 +3236,32 @@
{NULL, NULL} /* Sentinel */
};
+/************************************************************/
+/* Functions used by '_cffi_N.so', the generated modules */
+
+static char *_cffi_to_c_char_p(PyObject *obj)
+{
+ if (PyString_Check(obj)) {
+ return PyString_AS_STRING(obj);
+ }
+ if (obj == Py_None) {
+ return NULL;
+ }
+ if (CData_Check(obj)) {
+ return ((CDataObject *)obj)->c_data;
+ }
+ PyErr_Format(PyExc_TypeError,
+ "initializer for ctype 'char *' must be a compatible pointer, "
+ "not %.200s", Py_TYPE(obj)->tp_name);
+ return NULL;
+}
+
+static void *cffi_exports[] = {
+ _cffi_to_c_char_p,
+};
+
+/************************************************************/
+
void init_ffi_backend(void)
{
PyObject *m, *v;
@@ -3264,4 +3290,8 @@
return;
if (PyType_Ready(&CDataWithDestructor_Type) < 0)
return;
+
+ v = PyCObject_FromVoidPtr((void *)cffi_exports, NULL);
+ if (v == NULL || PyModule_AddObject(m, "_C_API", v) < 0)
+ return;
}
diff --git a/cffi/verifier.py b/cffi/verifier.py
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -20,14 +20,9 @@
modname = ffiplatform.undercffi_module_name()
filebase = os.path.join(ffiplatform.tmpdir(), modname)
- with open(filebase + 'module.c', 'w') as f:
+ with open(filebase + '.c', 'w') as f:
self.f = f
- self.prnt("#include <Python.h>")
- self.prnt()
- self.prnt('#define _cffi_from_c_double PyFloat_FromDouble')
- self.prnt('#define _cffi_to_c_double PyFloat_AsDouble')
- self.prnt('#define _cffi_from_c_float PyFloat_FromDouble')
- self.prnt('#define _cffi_to_c_float PyFloat_AsDouble')
+ self.prnt(cffimod_header)
self.prnt()
self.prnt(preamble)
self.prnt()
@@ -43,7 +38,7 @@
self.prnt('void init%s()' % modname)
self.prnt('{')
self.prnt(' Py_InitModule("%s", _cffi_methods);' % modname)
- self.prnt(' if (PyErr_Occurred()) return;')
+ self.prnt(' if (PyErr_Occurred() || _cffi_init()) return;')
self.generate("init")
self.prnt('}')
#
@@ -52,11 +47,11 @@
# XXX use more distutils?
import distutils.sysconfig
python_h = distutils.sysconfig.get_python_inc()
- err = os.system("gcc -I'%s' -O2 -shared %smodule.c -o %s.so" %
+ err = os.system("gcc -I'%s' -O2 -shared %s.c -o %s.so" %
(python_h, filebase, filebase))
if err:
raise ffiplatform.VerificationError(
- '%smodule.c: see compilation errors above' % (filebase,))
+ '%s.c: see compilation errors above' % (filebase,))
#
import imp
try:
@@ -75,15 +70,27 @@
# ----------
- def convert_to_c(self, tp, fromvar, tovar, errcode):
+ def convert_to_c(self, tp, fromvar, tovar, errcode, is_funcarg=False):
if isinstance(tp, model.PrimitiveType):
- self.prnt(' %s = _cffi_to_c_%s(%s);' % (
- tovar, tp.name.replace(' ', '_'), fromvar))
- self.prnt(' if (%s == (%s)-1 && PyErr_Occurred())' % (
- tovar, tp.name))
- self.prnt(' %s;' % errcode)
+ converter = '_cffi_to_c_%s' % tp.name.replace(' ', '_')
+ errvalue = '-1'
+ #
+ elif isinstance(tp, model.PointerType):
+ if (is_funcarg and
+ isinstance(tp.totype, model.PrimitiveType) and
+ tp.totype.name == 'char'):
+ converter = '_cffi_to_c_char_p'
+ else:
+ converter = '_cffi_to_c_pointer'
+ errvalue = 'NULL'
+ #
else:
raise NotImplementedError(tp)
+ #
+ self.prnt(' %s = %s(%s);' % (tovar, converter, fromvar))
+ self.prnt(' if (%s == (%s)%s && PyErr_Occurred())' % (
+ tovar, tp.get_c_name(''), errvalue))
+ self.prnt(' %s;' % errcode)
def get_converter_from_c(self, tp):
if isinstance(tp, model.PrimitiveType):
@@ -134,7 +141,8 @@
prnt()
#
for i, type in enumerate(tp.args):
- self.convert_to_c(type, 'arg%d' % i, 'x%d' % i, 'return NULL')
+ self.convert_to_c(type, 'arg%d' % i, 'x%d' % i, 'return NULL',
+ is_funcarg=True)
prnt()
#
prnt(' { %s%s(%s); }' % (
@@ -161,3 +169,39 @@
self.prnt(' {"%s", _cffi_f_%s, %s},' % (name, name, meth))
generate_cpy_function_init = generate_nothing
+
+
+cffimod_header = r'''
+#include <Python.h>
+
+#define _cffi_from_c_double PyFloat_FromDouble
+#define _cffi_to_c_double PyFloat_AsDouble
+#define _cffi_from_c_float PyFloat_FromDouble
+#define _cffi_to_c_float PyFloat_AsDouble
+
+#define _cffi_to_c_char_p ((char *(*)(PyObject *))_cffi_exports[0])
+
+
+static void **_cffi_exports;
+
+static int _cffi_init(void)
+{
+ PyObject *module = PyImport_ImportModule("_ffi_backend");
+ PyObject *c_api_object;
+
+ if (module == NULL)
+ return -1;
+
+ c_api_object = PyObject_GetAttrString(module, "_C_API");
+ if (c_api_object == NULL)
+ return -1;
+ if (!PyCObject_Check(c_api_object)) {
+ PyErr_SetNone(PyExc_ImportError);
+ return -1;
+ }
+ _cffi_exports = (void **)PyCObject_AsVoidPtr(c_api_object);
+ return 0;
+}
+
+/**********/
+'''
More information about the pypy-commit
mailing list