Skip to content Skip to sidebar Skip to footer

Swig With Python And C: Arguments

I have this function: void func(int* a, int b); Which I want to make available in python like so: func(list, int) ie, the user passes a list and an integer (telling the functions

Solution 1:

You can use a multi-argument typemap.

%typemap(in) (const int *a, int b) %{
    $2 = (int)PyList_Size($input);
    $1 = new int[$2];
    for(Py_ssize_t i = 0; i < $2; ++i)
        $1[i] = PyLong_AsLong(PyList_GET_ITEM($input,i));
%}

%typemap(freearg) (const int* a, int b) %{
    delete [] $1;
%}

This assumes you are passing in a list (hence the const int*). Since a Python list knows its size there is no need to pass the size as well. Also note there is no error checking in the above example.

With this you pass one Python object ($input) for the two parameters. b ($2) is initialized with the size and a ($1) allocates a new int array of that size. The elements of the array are copied to this array.

The freearg typemap provides the cleanup after the function is called.

You use it like this:

func([1,2,3,4,5])

If you want to return a list, the following can be used:

%typemap(in) (int *a, int b) %{
    $2 = (int)PyLong_AsLong($input);
    $1 = new int[$2];
%}

%typemap(argout) (int *a, int b) (PyObject* tmp) %{
    tmp = PyList_New($2);
    for(Py_ssize_t i = 0; i < $2; ++i)
        PyList_SET_ITEM(tmp, i, PyLong_FromLong($1[i]));
    $result = SWIG_Python_AppendOutput($result, tmp);
%}

%typemap(freearg) (int* a, int b) %{
    delete [] $1;
%}

Note non-const int *a. Python doesn't need a list as an input parameter to return one, so the input typemap just expects an integer (error checking removed for brevity). The argout typemap builds a Python list out of the values return and appends them to the output result.

Use it like this:

func(5)     # returns for example [1,2,3,4,5]

If func has a return value it will return [retval, [1,2,3,4,5]]

Solution 2:

I thought I saw that you can use %apply to copy the typemap-for-array-and-length typemap so SWIG uses it for your function arguments. Something like (can't check exact syntax right now):

%apply (int *ARRAY, int LENGTH) { (int* a, int b) };
voidfunc(int* a, int b);

Alternatly, take a look Converting Python list to a char **: you might be able to adapt it to int by replacing all "char *" with "int".

Post a Comment for "Swig With Python And C: Arguments"