I am currently struggling with ctypes. I am able to convert a python list to a float array and give it to the C-function. But i can't figure out how to return this array from the C-function back to a python list...
Python-Code
class Point(ctypes.Structure):
_fields_= [("a", ctypes.c_float * 4),
("aa", ctypes.c_int)]
floats = [1.0, 2.0, 3.0, 4.0]
FloatArray4 = (ctypes.c_float * 4)
parameter_array = FloatArray4(*floats)
test1 = clibrary.dosth
test1.argtypes = [ctypes.c_float * 4, ctypes.c_int]
test1.restype = ctypes.POINTER(Point)
struc = test1(parameter_array, 9)
p = (struc.contents.a)
print(p)
clibrary.free_memory(struc)
The C-function basically puts the parameter_array into a structure ant returns the structure.. C-Code:
#include <stdio.h>
#include <stdlib.h>
struct a{float *a;
int aa;
} ;
struct a *dosth(float *lsit, int x){
struct a *b = malloc(200000);
b -> a = lsit;
b -> aa = 3;
return b;
}
void free_memory(struct a *pointer){
free(pointer);
}
Output of print(p) in Python is :
<__main__.c_float_Array_4 object at 0x000001FE9EEA79C0>
How do i get access to those values?
CodePudding user response:
Slicing a ctypes
pointer will generate a Python list of the contents. Since a pointer has no knowledge of how many items it points to, you'll need to know the size, usually through another parameter:
>>> import ctypes as ct
>>> f = (ct.c_float * 4)(1,2,3,4)
>>> f
<__main__.c_float_Array_4 object at 0x00000216D6B7A840>
>>> f[:4]
[1.0, 2.0, 3.0, 4.0]
Here's a fleshed-out example based on your code:
test.c
#include <stdlib.h>
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
struct Floats {
float *fptr;
size_t size;
};
API struct Floats *alloc_floats(float *fptr, size_t size) {
struct Floats *pFloats = malloc(sizeof(struct Floats));
pFloats->fptr = fptr;
pFloats->size = size;
return pFloats;
}
API void free_floats(struct Floats *pFloats) {
free(pFloats);
}
test.py
import ctypes as ct
class Floats(ct.Structure):
_fields_= (('fptr', ct.POINTER(ct.c_float)), # Pointer, not array.
('size', ct.c_int)) # Used to know the size of the array pointed to.
# Display routine when printing this class.
# Note the slicing of the pointer to generate a Python list.
def __repr__(self):
return f'Floats({self.fptr[:self.size]})'
dll = ct.CDLL('./test')
dll.alloc_floats.argtypes = ct.POINTER(ct.c_float), ct.c_size_t
dll.alloc_floats.restype = ct.POINTER(Floats)
dll.free_floats.argtypes = ct.POINTER(Floats),
dll.free_floats.restype = None
data = (ct.c_float * 4)(1.0, 2.0, 3.0, 4.0)
p = dll.alloc_floats(data, len(data))
print(p.contents)
dll.free_floats(p)
Output:
Floats([1.0, 2.0, 3.0, 4.0])