Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to cast numpy.matrix to C double pointer

What is the canonical way of getting a numpy matrix as an argument to a C function which takes a double pointer?

Context: I'm using numpy to validate some C code-to wit, I have a C function which takes a const double ** const, and I'm using ctypes to call the .so from Python.

I've tried:

func.argtypes = ctypeslib.ndpointer(dtype=double, ndim=2, flags="C_CONTIGUOUS")

and passed the numpy matrix directly (didn't work), as well as

func.argtypes = ctypes.POINTER(ctypes.POINTER(ctypes.c_double))

and then passed the numpy matrix via various casts. Casting led to the Python error

TypeError: _type_ must have storage info

Note: This question came up a few years ago here, but there was no completely successful resolution.

like image 882
user14717 Avatar asked Dec 28 '14 23:12

user14717


Video Answer


1 Answers

I think you're looking for the ctypes interface in numpy's ndarrays (or matrix for that matter). You may have a look here for more information on numpy's manual.

Please note that numpy C-API stores ndarrays (or matrices for that matter) with a single pointer (see http://docs.scipy.org/doc/numpy/reference/c-api.types-and-structures.html#c.PyArrayObject). You cannot convert this single pointer into a double pointer in C, just because these are different types. Furthermore, numpy not only stores the data on these objects, it also stores information about the shape of the matrix and the strides (how the data is organised on the provided data pointer). Without knowing all these information, your code will not work on all conditions. For example, if you transpose a matrix before interfacing it to your code, you'll get unexpected results!

There are a couple of solutions depending on your settings:

  1. If you can modify your library's API, change it so that you can pass numpy information concerning not only the data pointer, but also the shape of the matrix and its strides. Then, use the above link to figure out how to interface numpy/ctypes support with your new API.

  2. If you cannot modify your API, I suggest you create a Python function based on ctypes that converts the contents of the numpy array into a double-pointer matrix created with ctypes itself (as suggested on this discussion). Also add support for the numpy object shape and stride so that you can run the conversion properly. After converting, pass the newly created double pointer structure to your original function.

like image 198
André Anjos Avatar answered Oct 21 '22 17:10

André Anjos