我有这个结构:
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;
}
我在函数中调用它:
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;
}
如果我在main中使用它,我只需拨打free(res.taken) in the end
。
但是我使用以下方法将其转换为共享库:
gcc -fPIC -c get_taken_values.c
ld -shared -soname libtest.so.1 -o my_library.so -lc get_taken_values.o
我将使用ctypes在Python中使用此库。
我是否需要释放calloc,如果是,我该怎么做?
答案 0 :(得分:1)
假设您需要taken
的可变大小数组,那么您可以创建一个ctypes.Structure
,为其提供一个__del__
方法,该方法将调用free
。您可以通过加载free
来致电libc
。在对象的最后一次引用超出范围之后调用__del__
。如果你的对象包含循环引用,使用__del__
可能会导致问题,因为python不会首先知道要调用__del__
的对象(所以它不会,它只是让对象在内存中保持不变)
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)
这假设python Result
的实例是内存的所有者。此外,如果taken
确实是可变大小的,那么您需要在Result
引用的结构中包含size成员。如果taken
是固定大小,那么您可以在结构中声明为数组,忘记使用free,并在声明{{1}类型时使用c_int * 9
而不是POINTER(c_int)
在python中。