Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning a C array from a C function to Python using ctypes

Tags:

python

c

ctypes

I'm currently trying to reduce the run time of Python program by writing a C function to do the heavy lifting on a very large array. At the moment I'm just working with this simple function.

int * addOne(int array[4])
{
    int i;
    for(i = 0; i < 5; i++)
    {
        array[i] = array[i] + 1;
    }
    return array;
}

All I want my Python code to do is call the C function and then have the new array returned. Here's what I have so far:

from ctypes import *
libCalc = CDLL("libcalci.so")
pyarr = [65, 66, 67, 68]
arr = (ctypes.c_int * len(pyarr))(*pyarr)
res = libCalc.addOne(arr)

How do I create a Python list from the returned pointer?

like image 408
Nicolas Avatar asked Feb 03 '26 11:02

Nicolas


1 Answers

The pointer you're returning is actually the same that you're passing. I.e. you don't actually need to return the array pointer.

You are handing over a pointer to the memory area backing the list from Python to C, the C function can then change that memory. Instead of returning the pointer, you can return an integer status code to flag whether everything went as expected.

int addOne(int array[4])
{
    int i;
    for(i = 0; i < 5; i++)
    {
        array[i] = array[i] + 1; //This modifies the underlying memory
    }
    return 0; //Return 0 for OK, 1 for problem.
}

From the Python side, you can view the results by inspecting arr.

from ctypes import *
libCalc = CDLL("libcalci.so")
pyarr = [65, 66, 67, 68]                   #Create List with underlying memory
arr = (ctypes.c_int * len(pyarr))(*pyarr)  #Create ctypes pointer to underlying memory
res = libCalc.addOne(arr)                  #Hands over pointer to underlying memory

if res==0:
    print(', '.join(arr))                  #Output array
like image 188
visibleman Avatar answered Feb 06 '26 02:02

visibleman