I have this struct:
struct result {
int position;
int *taken;
};
struct result get_result(int pos, int take[]){
struct result res;
res.position = pos;
res.taken = take;
return res;
}
Which I call in a function:
struct result get_taken_values(){
//some code
int position = 0;
int* chosen = calloc(9, sizeof(int));
//some more code
struct result res;
res.position = position;
res.taken = chosen;
return res;
}
If I were to use this in main, I would simply call free(res.taken) in the end
.
But I'm making this into a shared library using:
gcc -fPIC -c get_taken_values.c
ld -shared -soname libtest.so.1 -o my_library.so -lc get_taken_values.o
I'll be using this library in Python using ctypes.
Do I need to free the calloc, if so how do I do it?
Assuming you need a variable sized array for taken
, then you can create a ctypes.Structure
, give it a __del__
method that will call free
. You can call free
by loading libc
. __del__
is called after the last reference to an object falls out of scope. Using __del__
can cause problems if your objects contain circular references as python will not know which objects to call __del__
on first (so it doesn't, it just keeps the objects hanging around in memory).
from ctypes import Structure, c_int, POINTER, CDLL
from ctypes.util import find_library
__all__ = ["get_taken_values", "Result"]
libc = CDLL(find_library("c"))
libmy_library = CDLL("./my_library.so")
class Result(Structure):
_fields_ = [
("position", c_int),
("taken", POINTER(c_int)),
("size", c_int)
]
def __str__(self):
return "result(position={}, taken={})".format(
self.position, self.taken[:self.size])
def __del__(self):
libc.free(self.taken)
get_taken_values = libmy_library.get_taken_values
get_taken_values.argtypes = ()
get_taken_values.restype = Result
if __name__ == "__main__":
result = get_taken_values()
print("position is {} and value at position is {}".format(
result.position, result.taken[result.position]))
print(result)
This makes the assumption that the instance of the python Result
is the owner of the memory. Also, if taken
really is variable sized then you will need to include the size member in your struct that Result
references. If taken
is a fixed size then you can just declare taken as an array in the struct, forget about using free, and use c_int * 9
rather than POINTER(c_int)
when declaring the type of taken
in python.