简体   繁体   English

使用Swig将numpy字符串数组传递给C

[英]Passing numpy string array to C using Swig

my C program needs a char** input which I store in python as a numpy object array of strings. 我的C程序需要一个char**输入,我将它作为字符串的numpy对象数组存储在python中。

a = np.empty(2, dtype=object)
a[0] = 'hi you'
a[1] = 'goodbye'

What is the correct way to pass this to my C program considering that numpy.i only defines typemaps for char* arrays? 考虑到numpy.i仅为char*数组定义类型映射,将其传递给C程序的正确方法是什么?

That's impossibru AFAIK, and as far as the docs go : 那是不可能的 AFAIK, 就文档而言

Some data types are not yet supported, like boolean arrays and string arrays. 尚不支持某些数据类型,例如布尔数组和字符串数组。

You'll either have to write an intermediary function that takes the strings as separate arguments, put them in an array and pass that to your C function, or work out another way of doing things 您将不得不编写一个将字符串作为单独参数的中介函数,将其放入数组并将其传递给C函数,或者设计出另一种处理方式

So it is doable, but you need to convert the numpy object array to a list of python strings with a.tolist() . 因此这是可行的,但您需要使用a.tolist()将numpy对象数组转换为python字符串列表。 Then you can pass it to the C code with the following tutorial code as a char ** 然后,您可以将以下教程代码作为char **传递给C代码。

http://www.swig.org/Doc1.3/Python.html#Python_nn59 http://www.swig.org/Doc1.3/Python.html#Python_nn59

Edit: Turned out to be a real pain in the *** since the example above is for Python 2 but gives useless error messages in Python 3. Python 3 moved to unicode strings and I had to do some doc reading to make it work. 编辑:事实证明,这是***的真正痛苦,因为上面的示例是针对Python 2的,但是在Python 3中却给出了无用的错误消息。Python3移到了unicode字符串,我不得不做一些文档阅读才能使其工作。 Here is the python 3 equivalent of the above example. 这是上面示例的python 3等效项。

// This tells SWIG to treat char ** as a special case
%typemap(in) char ** {
  /* Check if is a list */
    if (PyList_Check($input)) {
        int size = PyList_Size($input);
        Py_ssize_t i = 0;
        $1 = (char **) malloc((size+1)*sizeof(char *));
        for (i = 0; i < size; i++) {
            PyObject *o = PyList_GetItem($input,i);
            if (PyUnicode_Check(o))
                $1[i] = PyUnicode_AsUTF8(PyList_GetItem($input,i));
            else {
                //PyErr_SetString(PyExc_TypeError,"list must contain strings");
                PyErr_Format(PyExc_TypeError, "list must contain strings. %d/%d element was not string.", i, size);
                free($1);
                return NULL;
            }
        }
        $1[i] = 0;
    } else {
        PyErr_SetString(PyExc_TypeError,"not a list");
        return NULL;
    }
}

// This cleans up the char ** array we malloc'd before the function call
%typemap(freearg) char ** {
  free((char *) $1);
}

Essentially just had to replace PyString_Check with PyUnicode_Check and PyString_AsString with PyUnicode_AsUTF8 (introduced in python 3.3 and later) 从本质上讲只是不得不更换PyString_CheckPyUnicode_CheckPyString_AsStringPyUnicode_AsUTF8 (在python推出3.3及更高版本)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM