1

I am having trouble combining C code with python via the ctypes library. I am trying to pass a python list into a C function which iterates over the list and modifies its values. I would now like to use the modified list in my python code.

C code - iterator.c

#include <math.h>

void apply_cosine(double *array,int length)
{
  for(int i = 0 ; i < length; i++){
      array[i] = cos(array[i]);
    }
}

Python code - python_base.py

import os
import ctypes

current_dir = os.getcwd()
full_path = current_dir + "/lib.so"

_lib = ctypes.CDLL(full_path)

_lib.apply_cosine.argtypes = (ctypes.POINTER(ctypes.c_double), ctypes.c_int)
# _lib.apply_cosine.restype = ctypes.c_double

def apply_cosine(array: list) -> list:
    '''Wrapper function to apply cosine function to each element in the list.
    '''
    length = len(array)
    array_type = ctypes.c_double * length
    array = _lib.apply_cosine(array_type(*array), ctypes.c_int(length))
    return array

if __name__ == "__main__":
    test = [12., 44., 23., 32., 244., 23.]
    print(apply_cosine(test))

I am pretty sure that my problem is the return type. My c code only modifies the list via a pointer and does not return the list explicitly. Hence, the in the c code modified list seems not to get passed back into the python code.

Do you have any suggestions on how to do this properly?

Thank you very much in advance for your help.

6
  • It looks like your function modifies the array inplace. Did you try not to assign the returned value, i.e. just calling _lib.apply_cosine(array_type(*array), ctypes.c_int(length)), without assigning anything to array? Commented Jul 25, 2022 at 20:44
  • @Marat thank you for the suggestion, unfortunately, the list is still unmodified. I am guessing that the problem is still based on returning the modified list back to python. Commented Jul 25, 2022 at 20:54
  • 1
    can you try this? Commented Jul 25, 2022 at 21:04
  • @Marat note that you could just return list(array) instead of the list comprehension Commented Jul 25, 2022 at 21:45
  • @SamMason good to know. I was not certain if ctypes lists suport iteration Commented Jul 25, 2022 at 21:48

1 Answer 1

1

For future reference, the code works with the suggestions from @Marat and @SamMason:

C code - iterator.c

#include <math.h>

void apply_cosine(double *array,int length)
{
  for(int i = 0 ; i < length; i++){
      array[i] = cos(array[i]);
    }
}

Python code - python_base.py

-> to build the shared library, use the command: gcc -fPIC -shared -o lib.so iterator.c

import os
import ctypes

current_dir = os.getcwd()
full_path = current_dir + "/lib.so"

_lib = ctypes.CDLL(full_path)

_lib.apply_cosine.argtypes = (ctypes.POINTER(ctypes.c_double), ctypes.c_int)

def apply_cosine(array: list) -> list:
    '''Wrapper function to apply cosine function to each element in the list.
    '''
    length = len(array)
    array = (ctypes.c_double * length)(*array)
    _lib.apply_cosine(array, length)
    return list(array)

if __name__ == "__main__":
    test = [12., 44., 23., 32., 244., 23.]
    test = apply_cosine(test)
    print(test)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.