2014-12-29 3 views
2

나는이 구조체가 .무료은 calloc은

하지만 사용하여 공유 라이브러리에이를 만들고 있어요 : 내가하는 ctypes를 사용하여 파이썬에서이 라이브러리를 사용할 것

gcc -fPIC -c get_taken_values.c 
ld -shared -soname libtest.so.1 -o my_library.so -lc get_taken_values.o 

.

만약 내가 그렇다면 calloc을 해제해야합니까?

+3

배열이 고정 된 크기이기 때문에 구조체에서'int taken [9]'를 정의하지 않는 것이 어떻습니까? 그러면'calloc'과'free'는 필요 없습니다. ctypes는'restype'에 설정된'ctypes.Structure' 서브 클래스를 처리하지만, 파이썬에서 구조체를 할당하고 수정할 함수에 대한 참조로 전달할 수도 있습니다. – eryksun

+3

당신은 필요한 정리를하는'free_taken_values ​​()'함수를 정의 할 수 있습니다. – jfs

답변

1

taken에 대해 가변 크기의 배열이 필요하다고 가정하면 __del__ 메서드를 사용하여 free을 호출하면 ctypes.Structure을 만들 수 있습니다. libc을로드하여 free으로 전화 할 수 있습니다. __del__은 개체에 대한 마지막 참조가 범위를 벗어난 후에 호출됩니다. __del__을 사용하면 객체가 순환 참조를 포함하는 경우 문제가 발생할 수 있습니다. 파이썬은 먼저 __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) 

이것은 파이썬 Result의 인스턴스가 메모리의 소유자라고 가정한다. 또한 taken이 실제로 크기가 가변적이라면 구조체에 Result 참조와 같은 크기 멤버를 포함시켜야합니다. 만약 taken이 고정 된 크기라면, 구조체의 배열로 선언하고, free를 사용하는 것을 잊어 버리고, taken을 파이썬에서 선언 할 때 POINTER(c_int) 대신에 c_int * 9을 사용하십시오.

+0

@eryksun 나는 glibc와 리눅스에 대한 경험이있다. Microsoft 런타임과 관련된 편집 내용을 직접 답변에 추가하는 것이 좋습니다. – Dunes

+0

@eryksun 아, 이제 알겠습니다. – Dunes

+0

당신의 접근 방법을 시도했는데, C에서 그것은'position : 69, taken [0] : 3, taken [1] : 9', python은 나에게 결과를 준다 (position = 69, moves = [5, -1]). POINTER (c_int)는 c_long으로 바뀌고 대신 int의 배열이어야합니다. –