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

时间:2015-10-23 16:10:45

标签: python c numpy swig

我的C程序需要一个char**输入,我将它存储在python中作为字符串的numpy对象数组。

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

考虑到numpy.i仅定义char*数组的类型映射,将此传递给我的C程序的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

impossibru AFAIK和as far as the docs go

  

尚不支持某些数据类型,如布尔数组和字符串数组。

您必须编写一个中间函数,将字符串作为单独的参数,将它们放在一个数组中并将其传递给您的C函数,或者制定另一种方法

答案 1 :(得分:1)

所以它是可行的,但你需要将numpy对象数组转换为a.tolist()的python字符串列表。然后,您可以将以下教程代码作为char **

传递给C代码

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

编辑:由于上面的示例适用于Python 2,但是在Python 3中提供了无用的错误消息,因此变成了***中真正的痛苦.Python 3转移到unicode字符串,我不得不做一些文档阅读来制作这行得通。这是与上面例子相同的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);
}

基本上只需将PyString_Check替换为PyUnicode_Check,将PyString_AsString替换为PyUnicode_AsUTF8(在python 3.3及更高版本中引入)