I'm trying to use ctypes in my python code test.py
to pass the array to test.c
and do some calculation and bring the result to python code.
Here is 'test.c'
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test.h"
void test(int N, complex *v){
int k;
for(k=0; k<N; k ){
v[k].Re = v[k].Re 1;
v[k].Im = v[k].Im 1;
printf("%d %f %f\n", k, v[k].Re, v[k].Im);
}
}
v is the structed array defined in test.h
typedef struct{float Re; float Im;} complex;
From Python I can do something like this
import numpy as np
from ctypes import cdll
from ctypes import *
class complex(Structure):
_fields_ = (('Re', POINTER(c_float)),
('Im', POINTER(c_float)))
def __init__(self, I, Q, lenIQ):
array_type = c_float * lenIQ
self.Re = array_type(*I)
self.Im = array_type(*Q)
def __repr__(self):
return f'Complex({self.Re}, {self.Im})'
cgmap = cdll.LoadLibrary('./test.dll')
test = cgmap.test
test.argtypes = (c_int, complex)
I = [2,2,3,4]
Q = [5,6,7,8]
lenIQ = len(I)
myarray = complex(I, Q, lenIQ)
test(c_int(lenIQ), myarray)
print(myarray)
print(myarray[0])
But when I execute test.py
, then :
0 4284182633119744.000000 1.000000
1 4585659272527872.000000 1.000000
2 3.983704 1.000000
3 3.983746 1.000000
Complex(<__main__.LP_c_float object at 0x0000029959825A48>, <__main__.LP_c_float object at 0x0000029959825A48>)
Traceback (most recent call last):
File "test.py", line 28, in <module>
print(myarray[0])
TypeError: 'complex' object does not support indexing
Is there anyway to solve without modifying test.c
? Any help would be appreciated ;)
CodePudding user response:
you are mixing up between creating a struct, creating an array of struct, and creating a pointer to an array of struct, those are 3 different operations, i have commented the code for clarity.
import numpy as np
from ctypes import cdll
from ctypes import *
class complex(Structure): # struct with two floats
_fields_ = (('Re', c_float),
('Im', c_float))
def __init__(self, I_val, Q_val):
self.Re = I_val
self.Im = Q_val
def __repr__(self):
return f'Complex({self.Re}, {self.Im})'
I = [2,2,3,4]
Q = [5,6,7,8]
lenIQ = len(I)
my_array_type = complex*lenIQ # create the type of array (complex[])
my_array = my_array_type() # create the array (complex my_array[4])
for i in range(len(I)):
my_array[i] = complex(I[i],Q[i]) # fill each individual object in the array
# next line is equivalent to "complex* pointer_to_array = (complex*)(my_array);"
pointer_to_array = cast(my_array, POINTER(complex)) # create the pointer to the first element of the array (complex*)
print(my_array) # prints type of my_array
print(my_array[0]) # equivalent to c's my_array[0]
print(pointer_to_array[0]) # equivalent to c's pointer_to_array[0]
<__main__.complex_Array_4 object at 0x000002195A9B8C40>
Complex(2.0, 5.0)
Complex(2.0, 5.0)
now for calling
cgmap = cdll.LoadLibrary('./test.dll')
test = cgmap.test
test.argtypes = (c_int, POINTER(complex))
test.restype = None
test(c_int(lenIQ), pointer_to_array)