diff options
Diffstat (limited to 'Examples/python/libffi/example.i')
-rw-r--r-- | Examples/python/libffi/example.i | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/Examples/python/libffi/example.i b/Examples/python/libffi/example.i new file mode 100644 index 0000000..9a29ec0 --- /dev/null +++ b/Examples/python/libffi/example.i @@ -0,0 +1,176 @@ +/* File : example.i */ +%module example + +%{ +#include <unistd.h> +#include <ffi.h> +%} + +/* A wrapper for execlp() using libffi to handle an arbitrary + number of arguments */ + +%typemap(in) (...) { + char **argv; + int argc; + int i; + + argc = PyTuple_Size(varargs); + argv = (char **) malloc(sizeof(char *)*(argc+1)); + for (i = 0; i < argc; i++) { + PyObject *o = PyTuple_GetItem(varargs,i); + if (!PyString_Check(o)) { + PyErr_SetString(PyExc_ValueError,"Expected a string"); + return NULL; + } + argv[i] = PyString_AsString(o); + } + argv[i] = NULL; + $1 = (void *) argv; +} + +/* Rewrite the function call, using libffi */ +%feature("action") execlp { + int i, vc; + ffi_cif cif; + ffi_type **types; + void **values; + char **args; + + vc = PyTuple_Size(varargs); + types = (ffi_type **) malloc((vc+3)*sizeof(ffi_type *)); + values = (void **) malloc((vc+3)*sizeof(void *)); + args = (char **) arg3; + + /* Set up path parameter */ + types[0] = &ffi_type_pointer; + values[0] = &arg1; + + /* Set up first argument */ + types[1] = &ffi_type_pointer; + values[1] = &arg2; + + /* Set up rest of parameters */ + for (i = 0; i <= vc; i++) { + types[2+i] = &ffi_type_pointer; + values[2+i] = &args[i]; + } + if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, vc+3, + &ffi_type_uint, types) == FFI_OK) { + ffi_call(&cif, (void (*)()) execlp, &result, values); + } else { + PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!"); + free(types); + free(values); + free(arg3); + return NULL; + } + free(types); + free(values); + free(arg3); +} + +int execlp(const char *path, const char *arg1, ...); + + +/* A wrapper for printf() using libffi */ + +%{ + typedef struct { + int type; + union { + int ivalue; + double dvalue; + void *pvalue; + } val; + } vtype; + enum { VT_INT, VT_DOUBLE, VT_POINTER }; + %} + +%typemap(in) (const char *fmt, ...) { + vtype *argv; + int argc; + int i; + + $1 = PyString_AsString($input); + + argc = PyTuple_Size(varargs); + argv = (vtype *) malloc(argc*sizeof(vtype)); + for (i = 0; i < argc; i++) { + PyObject *o = PyTuple_GetItem(varargs,i); + if (PyInt_Check(o)) { + argv[i].type = VT_INT; + argv[i].val.ivalue = PyInt_AsLong(o); + } else if (PyFloat_Check(o)) { + argv[i].type = VT_DOUBLE; + argv[i].val.dvalue = PyFloat_AsDouble(o); + } else if (PyString_Check(o)) { + argv[i].type = VT_POINTER; + argv[i].val.pvalue = (void *) PyString_AsString(o); + } else { + PyErr_SetString(PyExc_ValueError,"Unsupported argument type"); + free(argv); + return NULL; + } + } + + $2 = (void *) argv; +} + +/* Rewrite the function call, using libffi */ +%feature("action") printf { + int i, vc; + ffi_cif cif; + ffi_type **types; + void **values; + vtype *args; + + vc = PyTuple_Size(varargs); + types = (ffi_type **) malloc((vc+1)*sizeof(ffi_type *)); + values = (void **) malloc((vc+1)*sizeof(void *)); + args = (vtype *) arg2; + + /* Set up fmt parameter */ + types[0] = &ffi_type_pointer; + values[0] = &arg1; + + /* Set up rest of parameters */ + for (i = 0; i < vc; i++) { + switch(args[i].type) { + case VT_INT: + types[1+i] = &ffi_type_uint; + values[1+i] = &args[i].val.ivalue; + break; + case VT_DOUBLE: + types[1+i] = &ffi_type_double; + values[1+i] = &args[i].val.dvalue; + break; + case VT_POINTER: + types[1+i] = &ffi_type_pointer; + values[1+i] = &args[i].val.pvalue; + break; + default: + abort(); /* Whoa! We're seriously hosed */ + break; + } + } + if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, vc+1, + &ffi_type_uint, types) == FFI_OK) { + ffi_call(&cif, (void (*)()) printf, &result, values); + } else { + PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!"); + free(types); + free(values); + free(args); + return NULL; + } + free(types); + free(values); + free(args); +} + +int printf(const char *fmt, ...); + + + + + |