SWIG with python and C: arguments

旧巷老猫 提交于 2019-12-13 16:26:34

问题


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 how many entries should be stored in the list). To do this, I need to know the value of "b" in the initialization for "a" (because I need a raw C int array temporarily).

%typemap(in) ( int* a) {

//need to allocate sizeof(int) * b bytes temporarily

 }

But I don't know the value of "b" because it is only parsed later!

How can I access the value of the "b" argument?


回答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]]




回答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) };
void func(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".



来源:https://stackoverflow.com/questions/23015860/swig-with-python-and-c-arguments

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!