简体   繁体   中英

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.

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?

That's impossibru AFAIK, and as far as the docs go :

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

So it is doable, but you need to convert the numpy object array to a list of python strings with a.tolist() . Then you can pass it to the C code with the following tutorial code as a char **

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. Here is the python 3 equivalent of the above example.

// 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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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