Spiros Spiros - 4 years ago 338
Python Question

Simplest way to share an array when embedding Python

I'm writing a simulation in C++ and decided to delegate the initialization of some arrays to Python by embedding it into my application and use some Python functions for the generation of the initial data.

Since my 2D/3D arrays are allocated and managed by the C++ part, I need to pass them to Python. The best way is probably the buffer protocol. I could write a Python class in C++, which implements the buffer protocol and creates a buffer object to the storage I have in C++.

Now, I would like to avoid over-engineering this procedure. In facts, I just need to pass a pointer, a tuple of sizes and strides to a Python function.

The question is thus: What is the simplest way to pass this information to a Python routine which can then use it, possibly with Numpy, to initialize the pointed storage?

Just to give an example of what I need to do, the Python function I want to call from C++ is:

def init_field(field, X, Y):
field[:, :] = np.sqrt(X) + np.tanh(Y)


where
X
and
Y
are numpy arrays which are created by Python and borrowed by the C++ application and
field
is exactly this 2D array which is managed by C++. I could of course substitute
field
with one or more parameters carrying information about the pointer, the sizes and the strides and construct the numpy array. How do I do that?

Answer Source

Something not too hard is to use PyArray_SimpleNewFromData. Using that might lead to code like:

void use_array(float* ptr, int width, int height)
{
    PyObject *pFunc = pyFunction("python_function_name");
    if (pFunc == 0)
        return;
    PyObject *pArgs = PyTuple_New(1);
    npy_intp dims[2];
    dims[1] = width;
    dims[0] = height;
    PyTuple_SetItem(pArgs, 0, PyArray_SimpleNewFromData(2, dims, NPY_FLOAT, ptr));
    PyObject *pValue = PyObject_CallObject(pFunc, pArgs);
    Py_DECREF(pArgs);
    if (pValue != NULL) {
        Py_DECREF(pValue);
    }
    else 
    {
        PyErr_Print();
        fprintf(stderr,"Call failed\n");
        return;
    }
    Py_DECREF(pFunc);
}

When setting up the embedded Python environment you should call import_array() as described in http://docs.scipy.org/doc/numpy-1.10.0/reference/c-api.array.html#miscellaneous

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download