As the title says I have been trying for the last 48 hours to pass vectors from a python project to a set of C functions I have written. Eventually I came to the conclusion it might be easier using arrays instead of vectors based on some reading around of past posts on here. This led to me trying this tutorial below BUT it was originally only for exemplifying passing in an integer and returning it too. I tried changing the code so it would pass by reference a 3 number long list/array from python, and then add 1 to each of the numbers in it. However, when I run this, I can see it is getting the array no problem and printing the values modified in the c function, but it's not modifying the original python variable. In fact what I get "<class 'main.c_double_Array_3'>" back when I try to print output of the wrapper function. Below is the code I've tried so far (in its current state). If anyone could provide some direction regarding a resource for a good clear tutorial on how to do this, OR some help regarding what to do I would greatly appreciate it.
Simple_calculations C file
extern "C" void our_function(double * numbers) {
numbers[0] = 1;
numbers[1] = 1;
numbers[2] = 1;
std::cout << numbers[0] << std::endl;
std::cout << numbers[1] << std::endl;
std::cout << numbers[2] << std::endl;
}
Python file
import os
import ctypes
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
os.system('g -dynamiclib -shared -o simple_calculations.dylib simple_calculations.cpp -std=c 17')
_sum = ctypes.CDLL('simple_calculations.dylib')
_sum.our_function.argtypes = (ctypes.POINTER(ctypes.c_double),)
def our_function(numbers):
array_type = ctypes.c_double * 3
_sum.our_function(array_type(*numbers))
return array_type
z = our_function([0, 1, 2])
print(z)
Output
1
2
3
<class '__main__.c_double_Array_3'>
CodePudding user response:
You are returning array_type
. That’s a type, not an instance of the type. The instance is your array_type(*numbers)
passed to the function, but it is not preserved. Assign it to a variable and return that, or better yet convert it back to a Python list as shown below:
test.cpp
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
extern "C" API void our_function(double * numbers) {
numbers[0] = 1;
numbers[1] = 1;
numbers[2] = 1;
}
test.py
import ctypes
_sum = ctypes.CDLL('./test')
_sum.our_function.argtypes = ctypes.POINTER(ctypes.c_double),
def our_function(numbers):
array_type = ctypes.c_double * 3 # equiv. to C double[3] type
arr = array_type(*numbers) # equiv. to double arr[3] = {...} instance
_sum.our_function(arr) # pointer to array passed to function and modified
return list(arr) # extract Python floats from ctypes-wrapped array
z = our_function([0, 1, 2])
print(z)
Output:
[1.0, 2.0, 3.0]