blob: 9a29ec04ea8c6209cc7e08468bca758a8ffeebfa [file] [log] [blame]
/* 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, ...);