Search code examples
numpypython-c-apipython-c-extension

how to resize and subtract numpy arrays in c++


I have two numpy 3D-array in python with different height and width. I want to pass them to my C-Extension. How can I resize and subtract them in c++? Please see the comments in the code.

static PyObject *my_func(PyObject *self, PyObject     *args)
{
    Py_Initialize();
    import_array();


    PyObject *arr1;
    PyObject *arr2;

    if(!PyArg_ParseTuple(args, "OO", &arr1, &arr2)) 
    {
        return NULL;
    }

    //How can I do this?

    //resize arr1 to [100, 100, 3]
    //resize arr2 to [100, 100, 3]
    //res = arr1 - arr2
    //return res
}

Solution

  • Start by making the desired shape. It's easier to do this as a tuple than a list:

    PyObject* shape = Py_BuildValue("iii",100,100,3);
    

    Check this against NULL to ensure do error has occurred and handle if it has.

    You can call the numpy resize function on both arrays to resize them. Unless you are certain that the data isn't shared then you need to call numpy.resize rather than the .resize method of the arrays. This involves importing the module and getting the resize attribute:

    PyObject* np = PyImport_ImportModule("numpy");
    PyObject* resize = PyObject_GetAttrString(np,"resize");
    PyObject* resize_result = PyObject_CallFunctionObjArgs(resize,arr1, shape,NULL);
    

    I've omitted all the error checking, which you should do after each stage.

    Make sure you decrease the reference counts on the various PyObjects once you don't need them any more.

    Use PyNumber_Subtract to do the subtraction (do it on the result from resize).


    Addition: A shortcut for calling resize that should avoid most of the intermediates:

     PyObject* np = PyImport_ImportModule("numpy");
     // error check against null
     PyObject* resize_result = PyObject_CallMethod(np,"resize","O(iii)",arr1,100,100,3);
    

    (The "(iii)" creates the shape tuple rather than needing to do it separately.)


    If you are certain that arr1 and arr2 are the only owners of the data then you can call the numpy .resize method either by the normal C API function calls or the specific numpy function PyArray_Resize.