[pypy-commit] creflect default: in-progress: simple function calls
arigo
noreply at buildbot.pypy.org
Mon Dec 1 13:19:13 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r135:083a62ba609e
Date: 2014-12-01 13:19 +0100
http://bitbucket.org/cffi/creflect/changeset/083a62ba609e/
Log: in-progress: simple function calls
diff --git a/zeffir/test/function.crx b/zeffir/test/function.crx
new file mode 100644
--- /dev/null
+++ b/zeffir/test/function.crx
@@ -0,0 +1,11 @@
+// CREFLECT: start
+
+int simple_function(int);
+
+// CREFLECT: end
+
+
+int simple_function(int x)
+{
+ return x + 1;
+}
diff --git a/zeffir/test/test_function.py b/zeffir/test/test_function.py
new file mode 100644
--- /dev/null
+++ b/zeffir/test/test_function.py
@@ -0,0 +1,8 @@
+import support
+
+
+def test_simple_function():
+ ffi, lib = support.compile_and_open('function')
+ res = lib.simple_function(42)
+ assert type(res) is int
+ assert res == 43
diff --git a/zeffir/zef_builder.c b/zeffir/zef_builder.c
--- a/zeffir/zef_builder.c
+++ b/zeffir/zef_builder.c
@@ -4,9 +4,9 @@
typedef struct {
_crx_builder_t cb;
- PyLibObject *lib;
- PyFFIObject *ffi;
- PyObject *dict;
+ ZefLibObject *lib;
+ ZefFFIObject *ffi;
+ PyObject *l_dict;
} zeffir_builder_t;
static PyObject *zef_cache_primitive_signed;
@@ -157,13 +157,22 @@
_crx_type_t *ret, _crx_qual_type args[], int nargs,
_crx_trampoline0_fn trampl, void *directcall)
{
- abort();
+ PyObject *l_dict = ((zeffir_builder_t *)cb)->l_dict;
+ ZefFFIObject *ffi = ((zeffir_builder_t *)cb)->ffi;
+
+ assert(trampl != NULL);
+ PyObject *x = make_builtin_func(ffi, name, ret, args, nargs, trampl);
+ if (x == NULL)
+ return;
+
+ PyDict_SetItemString(l_dict, name, x);
+ Py_DECREF(x);
}
static void zef_define_num_const(_crx_builder_t *cb, const char *name,
_crx_type_t *ct, _crx_num_const_t *value)
{
- PyObject *dict = ((zeffir_builder_t *)cb)->dict;
+ PyObject *l_dict = ((zeffir_builder_t *)cb)->l_dict;
assert(ct->ct_flags & CT_PRIMITIVE_ANY);
@@ -171,7 +180,7 @@
if (x == NULL)
return;
- PyDict_SetItemString(dict, name, x);
+ PyDict_SetItemString(l_dict, name, x);
Py_DECREF(x);
}
@@ -180,26 +189,27 @@
abort();
}
-static int load_creflect_main(PyLibObject *lib)
+static int load_creflect_main(ZefLibObject *lib)
{
const char *creflect_main = "_creflect_main"; /* XXX fixed for now */
int (*crxmain)(_crx_builder_t *);
- crxmain = (int(*)(_crx_builder_t *))dlsym(lib->ffi->dl_lib, creflect_main);
+ crxmain = (int(*)(_crx_builder_t *))dlsym(lib->ffi->f_dl_lib,
+ creflect_main);
if (crxmain == NULL) {
PyErr_Format(PyExc_OSError, "%s: symbol '%s' not found",
- lib->ffi->libname, creflect_main);
+ lib->ffi->f_libname, creflect_main);
return -1;
}
int result = crxmain(NULL);
if ((result & ~0xFF) != MAGIC_CREFLECT_TAG) {
PyErr_Format(PyExc_OSError, "%s: %s() is not a creflect entry point",
- lib->ffi->libname, creflect_main);
+ lib->ffi->f_libname, creflect_main);
return -1;
}
if ((result & 0xFF) != CREFLECT_VERSION) {
PyErr_Format(PyExc_OSError, "%s was made with creflect version %d, "
- "expected %d", lib->ffi->libname, result & 0xFF,
+ "expected %d", lib->ffi->f_libname, result & 0xFF,
CREFLECT_VERSION);
return -1;
}
@@ -230,11 +240,12 @@
zef_define_num_const,
zef_error,
},
- lib, /* lib */
- lib->ffi, /* ffi */
- lib->dict, /* dict */
+ lib, /* lib */
+ lib->ffi, /* ffi */
+ lib->l_dict, /* l_dict */
};
crxmain(&builder.cb);
+
return PyErr_Occurred() ? -1 : 0;
}
diff --git a/zeffir/zef_cdata.c b/zeffir/zef_cdata.c
new file mode 100644
--- /dev/null
+++ b/zeffir/zef_cdata.c
@@ -0,0 +1,1 @@
+
diff --git a/zeffir/zef_cfunc.c b/zeffir/zef_cfunc.c
new file mode 100644
--- /dev/null
+++ b/zeffir/zef_cfunc.c
@@ -0,0 +1,96 @@
+
+typedef struct {
+ PyObject_HEAD
+
+ ZefFFIObject *zfs_ffi;
+ int zfs_nargs;
+ _crx_trampoline0_fn zfs_trampl;
+ PyMethodDef zfs_md;
+ char zfs_funcname[1];
+
+} ZefFuncSupportObject;
+
+static void zef_builtin_support_dealloc(ZefFuncSupportObject *zfs)
+{
+ Py_DECREF(zfs->zfs_ffi);
+ PyObject_Del(zfs);
+}
+
+static PyTypeObject ZefFuncSupport_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "zeffir.BuiltinSupport",
+ sizeof(ZefFuncSupportObject),
+ 0,
+ (destructor)zef_builtin_support_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+};
+
+static PyObject *zfs_call(PyObject *self, PyObject *args)
+{
+ ZefFuncSupportObject *zfs = (ZefFuncSupportObject *)self;
+ int i, nargs = zfs->zfs_nargs;
+ Py_ssize_t actualnargs;
+ void *llargs[nargs];
+ int llinput[nargs], lloutput; /* temp */
+
+ actualnargs = PyTuple_Size(args);
+ if (actualnargs != nargs) {
+ if (!PyErr_Occurred())
+ PyErr_Format(PyExc_TypeError, "'%s' expects %d arguments, got %zd",
+ zfs->zfs_funcname, nargs, actualnargs);
+ return NULL;
+ }
+
+ for (i = 0; i < nargs; i++) {
+ llinput[i] = PyInt_AsLong(PyTuple_GET_ITEM(args, i));
+ if (PyErr_Occurred())
+ return NULL;
+ llargs[i] = &llinput[i];
+ }
+
+ zfs->zfs_trampl(llargs, &lloutput);
+
+ return PyInt_FromLong(lloutput);
+}
+
+static PyObject *make_builtin_func(ZefFFIObject *ffi, const char *funcname,
+ _crx_type_t *ret,
+ _crx_qual_type args[], int nargs,
+ _crx_trampoline0_fn trampl)
+{
+ size_t size = sizeof(ZefFuncSupportObject) + strlen(funcname);
+ ZefFuncSupportObject *zfs = (ZefFuncSupportObject *)PyObject_Malloc(size);
+ if (zfs == NULL)
+ return PyErr_NoMemory();
+ PyObject_Init((PyObject *)zfs, &ZefFuncSupport_Type);
+
+ Py_INCREF(ffi);
+ zfs->zfs_ffi = ffi;
+ zfs->zfs_nargs = nargs;
+ zfs->zfs_trampl = trampl;
+
+ memset(&zfs->zfs_md, 0, sizeof(PyMethodDef));
+ zfs->zfs_md.ml_name = strcpy(zfs->zfs_funcname, funcname);
+ zfs->zfs_md.ml_meth = &zfs_call;
+ zfs->zfs_md.ml_flags = METH_VARARGS;
+ /*zfs->zfs_md.ml_doc = ... */
+
+ PyObject *res = PyCFunction_NewEx(&zfs->zfs_md, (PyObject *)zfs,
+ ffi->f_libname_obj);
+ Py_DECREF(zfs);
+ return res;
+}
diff --git a/zeffir/zef_ffi_obj.c b/zeffir/zef_ffi_obj.c
--- a/zeffir/zef_ffi_obj.c
+++ b/zeffir/zef_ffi_obj.c
@@ -1,27 +1,28 @@
-struct PyFFIObject_s {
+struct ZefFFIObject_s {
PyObject_HEAD
- void *dl_lib;
- char *libname;
+ void *f_dl_lib; /* keep the library returned by 'dlopen()' */
+ char *f_libname; /* the original argument to 'dlopen()' */
+ PyObject *f_libname_obj; /* same, as a PyObject */
};
-static void ffi_dealloc(PyFFIObject *ffi)
+static void ffi_dealloc(ZefFFIObject *ffi)
{
- if (ffi->dl_lib != NULL)
- dlclose(ffi->dl_lib);
- free(ffi->libname);
+ if (ffi->f_dl_lib != NULL)
+ dlclose(ffi->f_dl_lib);
+ Py_DECREF(ffi->f_libname_obj);
PyObject_Del(ffi);
}
-static PyObject *ffi_repr(PyFFIObject *ffi)
+static PyObject *ffi_repr(ZefFFIObject *ffi)
{
- return PyString_FromFormat("<zeffir.FFI object for '%s'>", ffi->libname);
+ return PyString_FromFormat("<zeffir.FFI object for '%s'>", ffi->f_libname);
}
-static PyTypeObject FFI_Type = {
+static PyTypeObject ZefFFI_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"zeffir.FFI",
- sizeof(PyFFIObject),
+ sizeof(ZefFFIObject),
0,
(destructor)ffi_dealloc, /* tp_dealloc */
0, /* tp_print */
diff --git a/zeffir/zef_funcs.c b/zeffir/zef_funcs.c
deleted file mode 100644
--- a/zeffir/zef_funcs.c
+++ /dev/null
@@ -1,77 +0,0 @@
-
-static PyObject *b_open(PyObject *self, PyObject *args, PyObject *kwds)
-{
- char *keywords[] = {"libname", "relative_to", NULL};
- char *libname, *relative_to;
- char *path;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", keywords,
- &libname, &relative_to))
- return NULL;
-
- char *last_slash = strrchr(relative_to, '/');
- if (last_slash == NULL) {
- relative_to = "./";
- last_slash = relative_to + 1;
- }
- size_t n = last_slash + 1 - relative_to;
- path = malloc(n + strlen(libname) + 16);
- if (path == NULL)
- return PyErr_NoMemory();
- memcpy(path, relative_to, n);
- strcpy(path + n, "lib");
- strcat(path + n, libname);
- strcat(path + n, ".so");
-
- PyFFIObject *ffi = NULL;
- PyLibObject *lib = NULL;
- PyObject *dict = NULL;
-
- dlerror(); /* clear errors */
- void *dl_lib = dlopen(path, RTLD_LAZY);
- if (dl_lib == NULL) {
- char *error = dlerror();
- if (error == NULL)
- error = "failed to open";
- PyErr_Format(PyExc_OSError, "%s: %s", path, error);
- goto error;
- }
-
- ffi = PyObject_New(PyFFIObject, &FFI_Type);
- if (ffi == NULL)
- goto error;
- ffi->dl_lib = dl_lib; dl_lib = NULL;
- ffi->libname = path; path = NULL;
-
- dict = PyDict_New();
- if (dict == NULL)
- goto error;
-
- lib = PyObject_New(PyLibObject, &Lib_Type);
- if (lib == NULL)
- goto error;
- lib->ffi = ffi; ffi = NULL;
- lib->dict = dict; dict = NULL;
-
- if (load_creflect_main(lib) < 0)
- goto error;
-
- PyObject *result = Py_BuildValue("OO", lib->ffi, lib);
- Py_DECREF(lib);
- return result;
-
- error:
- Py_XDECREF(dict);
- Py_XDECREF(lib);
- Py_XDECREF(ffi);
- if (dl_lib != NULL)
- dlclose(dl_lib);
- free(path);
- return NULL;
-}
-
-
-static PyMethodDef ZeffirMethods[] = {
- {"open", (PyCFunction)b_open, METH_KEYWORDS},
- {NULL, NULL} /* Sentinel */
-};
diff --git a/zeffir/zef_lib_obj.c b/zeffir/zef_lib_obj.c
--- a/zeffir/zef_lib_obj.c
+++ b/zeffir/zef_lib_obj.c
@@ -1,26 +1,26 @@
-struct PyLibObject_s {
+struct ZefLibObject_s {
PyObject_HEAD
- PyObject *dict;
- PyFFIObject *ffi;
+ PyObject *l_dict;
+ ZefFFIObject *ffi;
};
-static void lib_dealloc(PyLibObject *lib)
+static void lib_dealloc(ZefLibObject *lib)
{
- Py_DECREF(lib->dict);
+ Py_DECREF(lib->l_dict);
Py_DECREF(lib->ffi);
PyObject_Del(lib);
}
-static PyObject *lib_repr(PyLibObject *lib)
+static PyObject *lib_repr(ZefLibObject *lib)
{
return PyString_FromFormat("<zeffir.Lib object for '%s'>",
- lib->ffi->libname);
+ lib->ffi->f_libname);
}
static PyObject *lib_dir(PyObject *lib, PyObject *noarg)
{
- return PyDict_Keys(((PyLibObject *)lib)->dict);
+ return PyDict_Keys(((ZefLibObject *)lib)->l_dict);
}
static PyMethodDef lib_methods[] = {
@@ -29,14 +29,14 @@
};
static PyMemberDef lib_members[] = {
- {"__dict__", T_OBJECT, offsetof(PyLibObject, dict), READONLY},
+ {"__dict__", T_OBJECT, offsetof(ZefLibObject, l_dict), READONLY},
{NULL}
};
-static PyTypeObject Lib_Type = {
+static PyTypeObject ZefLib_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"zeffir.Lib",
- sizeof(PyLibObject),
+ sizeof(ZefLibObject),
0,
(destructor)lib_dealloc, /* tp_dealloc */
0, /* tp_print */
@@ -68,5 +68,5 @@
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
- offsetof(PyLibObject, dict), /* tp_dictoffset */
+ offsetof(ZefLibObject, l_dict), /* tp_dictoffset */
};
diff --git a/zeffir/zeffir.c b/zeffir/zeffir.c
--- a/zeffir/zeffir.c
+++ b/zeffir/zeffir.c
@@ -6,8 +6,8 @@
typedef struct _crx_type_s CTypeDescrObject;
-typedef struct PyLibObject_s PyLibObject;
-typedef struct PyFFIObject_s PyFFIObject;
+typedef struct ZefLibObject_s ZefLibObject;
+typedef struct ZefFFIObject_s ZefFFIObject;
/************************************************************/
@@ -15,13 +15,91 @@
/* Allows all function and global symbols to remain static. */
#include "zef_ctype.c"
+#include "zef_cdata.c"
#include "zef_ffi_obj.c"
#include "zef_lib_obj.c"
+#include "zef_cfunc.c"
#include "zef_builder.c"
-#include "zef_funcs.c"
/************************************************************/
+
+static PyObject *z_open(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ char *keywords[] = {"libname", "relative_to", NULL};
+ char *libname, *relative_to, *relative_dir;
+ PyObject *path;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", keywords,
+ &libname, &relative_to))
+ return NULL;
+
+ char *last_slash = strrchr(relative_to, '/');
+ if (last_slash == NULL)
+ relative_dir = strdup(".");
+ else
+ relative_dir = strndup(relative_to, last_slash - relative_to);
+ if (relative_dir == NULL)
+ return PyErr_NoMemory();
+
+ path = PyString_FromFormat("%s/lib%s.so", relative_dir, libname);
+ free(relative_dir);
+ if (path == NULL)
+ return NULL;
+
+ ZefFFIObject *ffi = NULL;
+ ZefLibObject *lib = NULL;
+ PyObject *dict = NULL;
+
+ dlerror(); /* clear errors */
+ void *dl_lib = dlopen(PyString_AS_STRING(path), RTLD_LAZY);
+ if (dl_lib == NULL) {
+ char *error = dlerror();
+ if (error == NULL)
+ error = "failed to open";
+ PyErr_Format(PyExc_OSError, "%s: %s", PyString_AS_STRING(path), error);
+ goto error;
+ }
+
+ ffi = PyObject_New(ZefFFIObject, &ZefFFI_Type);
+ if (ffi == NULL)
+ goto error;
+ ffi->f_dl_lib = dl_lib; dl_lib = NULL;
+ ffi->f_libname = PyString_AS_STRING(path);
+ ffi->f_libname_obj = path; path = NULL;
+
+ dict = PyDict_New();
+ if (dict == NULL)
+ goto error;
+
+ lib = PyObject_New(ZefLibObject, &ZefLib_Type);
+ if (lib == NULL)
+ goto error;
+ lib->ffi = ffi; ffi = NULL;
+ lib->l_dict = dict; dict = NULL;
+
+ if (load_creflect_main(lib) < 0)
+ goto error;
+
+ PyObject *result = Py_BuildValue("OO", lib->ffi, lib);
+ Py_DECREF(lib);
+ return result;
+
+ error:
+ Py_XDECREF(dict);
+ Py_XDECREF(lib);
+ Py_XDECREF(ffi);
+ if (dl_lib != NULL)
+ dlclose(dl_lib);
+ Py_XDECREF(path);
+ return NULL;
+}
+
+static PyMethodDef ZeffirMethods[] = {
+ {"open", (PyCFunction)z_open, METH_KEYWORDS},
+ {NULL, NULL} /* Sentinel */
+};
+
PyMODINIT_FUNC
initzeffir(void)
{
@@ -34,8 +112,12 @@
if (PyErr_Occurred())
return;
- if (PyType_Ready(&FFI_Type) < 0)
+ if (PyType_Ready(&ZefFFI_Type) < 0)
return;
- if (PyType_Ready(&Lib_Type) < 0)
+ if (PyType_Ready(&ZefLib_Type) < 0)
+ return;
+ if (PyType_Ready(&CTypeDescr_Type) < 0)
+ return;
+ if (PyType_Ready(&ZefFuncSupport_Type) < 0)
return;
}
More information about the pypy-commit
mailing list