문제

나는 약간의 ctypes 바인딩이 있고, 각 신체에 대해, 나는 Body.free를 불러야합니다. 내가 바인딩하는 라이브러리에는 코드의 나머지 부분에서 절연 된 할당 루틴이 없으며 (어디서나 호출 할 수 있음), 주기적 참조를하는 데 필요한 몇 가지 유용한 기능을 사용합니다.

나는 파괴자를 물체에 연결하는 신뢰할 수있는 방법을 찾으면 해결 될 것이라고 생각합니다. (약점은 콜백을 주면 도움이 될 것입니다. ~ 전에 데이터가 삭제됩니다.

velocity_func을 넣을 때이 코드 메가 페일 : 분명히 :

class Body(object):
    def __init__(self, mass, inertia):
        self._body = body.New(mass, inertia)

    def __del__(self):
        print '__del__ %r' % self
        if body:
            body.Free(self._body)

    ...        

    def set_velocity_func(self, func):
        self._body.contents.velocity_func = ctypes_wrapping(func)

나는 또한 약점을 통해 그것을 해결하려고 노력했는데, 그 사람들은 단지 악화되는 것처럼 보이며, 단지 예측할 수 없을 만합니다.

velocity_func를 넣지 않더라도 적어도 내가 이것을 할 때 사이클이 나타납니다.

class Toy(object):
    def __init__(self, body):
        self.body.owner = self

...

def collision(a, b, contacts):
    whatever(a.body.owner)

그렇다면 공유 라이브러리에 의해 할당/해제 되더라도 구조물이 쓰레기를 수집 할 수 있는지 확인하는 방법은 무엇입니까?

자세한 내용에 관심이있는 경우 저장소가 있습니다. http://bitbucket.org/cheery/ctypes-chipmunk/

도움이 되었습니까?

해결책 3

약점이 깨지지 않으면 이것이 효과가있을 것 같아요.

from weakref import ref

pointers = set()

class Pointer(object):
    def __init__(self, cfun, ptr):
        pointers.add(self)
        self.ref = ref(ptr, self.cleanup)
        self.data = cast(ptr, c_void_p).value # python cast it so smart, but it can't be smarter than this.
        self.cfun = cfun

    def cleanup(self, obj):
        print 'cleanup 0x%x' % self.data
        self.cfun(self.data)
        pointers.remove(self)

def cleanup(cfun, ptr):
    Pointer(cfun, ptr)

나는 아직 그것을 시도한다. 중요한 부분은 포인터가 정수를 제외한 외래 포인터에 대한 강력한 언급이 없다는 것입니다. CTYPES가 메모리를 자유롭게하지 않으면 바인딩으로 자유롭게 해야하는 경우 작동해야합니다. 예, 그것은 기본적으로 해킹이지만, 나는 그것이 내가 시도한 이전의 것보다 더 잘 작동 할 것이라고 생각합니다.

편집 : 시도해 보았고 코드를 작은 양조 한 후 작동하는 것 같습니다. 놀라운 것은 내가 얻더라도 있다는 것입니다 내 모든 구조에서 벗어나면 여전히 실패하는 것 같습니다. 흥미롭지 만 실망 스럽습니다.

이상한 기회부터 나는 그 장소에서 주기적 참조를 떨어 뜨릴 수 있었지만 상황은 파손되었습니다.

편집 : 글쎄 .. 약점은 결국 부러졌다! 따라서 파이썬에서 신뢰할 수있는 정리를위한 솔루션은 없을 것입니다.

다른 팁

당신이하고 싶은 일, 그것은 물건을 할당 한 다음 객체가 더 이상 사용되지 않을 때 자동으로 거래하는 객체를 생성하는 것이 불행히도 파이썬에서는 거의 불가능합니다. 그만큼 진술은 부름을받지 않으므로 이에 의존 할 수 없습니다.

파이썬의 표준 방법은 간단합니다.

try:
    allocate()
    dostuff()
finally:
    cleanup()

또는 2.5 이후로 컨텍스트 관리자를 만들고 with 문을 사용할 수 있습니다.

그러나이 두 가지 모두 주로 코드 스 니펫의 시작 부분에 할당/잠그는 경우입니다. 프로그램의 전체 실행에 물건을 할당하려면 프로그램의 기본 코드가 실행되기 전에 시작시 리소스를 할당하고 나중에 거래해야합니다. 여기서 다루지 않는 한 가지 상황이 있으며, 이는 많은 리소스를 동적으로 할당하고 거래하고 코드의 여러 곳에서 사용하려는 경우입니다. 예를 들어 메모리 버퍼 풀 또는 이와 유사한 풀을 원합니다. 그러나 이러한 사례의 대부분은 Python이 당신을 위해 처리 할 메모리를위한 것이므로, 당신은 그것에 대해 귀찮게 할 필요가 없습니다. 물론 메모리가 아닌 것들을 동적 풀 할당하고 싶은 경우가 있으며, 예에서 시도해 보는 거래 유형을 원할 것입니다. ~이다 파이썬과 관련하여 까다 롭습니다.

Cpython에서 __del__ ~이다 참조 수가 0에 도달 할 때 항상 호출되기 때문에 물체의 신뢰할 수있는 파괴자 (참고 : 항목의 원형 참조와 같이 경우가있을 수 있습니다. __del__ 정의 된 메소드 - 참조 수가 0에 도달하지 않지만 다른 문제입니다).

업데이트의견에서, 나는 문제가 물체의 파괴 순서와 관련이 있다는 것을 이해한다. 신체 글로벌 대상이며 다른 모든 물체보다 먼저 파괴되고 있으므로 더 이상 사용할 수 없습니다.
실제로 글로벌 객체를 사용하는 것은 좋지 않습니다. 이와 같은 문제뿐만 아니라 유지 보수로 인해 발생합니다.

그런 다음 이런 식으로 수업을 바꿀 것입니다.

class Body(object):
    def __init__(self, mass, inertia):
        self._bodyref = body
        self._body = body.New(mass, inertia)

    def __del__(self):
        print '__del__ %r' % self
        if body:
            body.Free(self._body)

...        

def set_velocity_func(self, func):
    self._body.contents.velocity_func = ctypes_wrapping(func)

몇 가지 메모 :

  1. 변경 사항은 글로벌에 대한 참조 만 추가하는 것입니다. 신체 따라서, 그것은 적어도 해당 클래스에서 파생 된 모든 객체만큼이나 살 것입니다.
  2. 그럼에도 불구하고 단위 테스트 및 유지 보수로 인해 글로벌 객체를 사용하는 것이 좋지 않습니다. 객체에 대한 공장을 갖는 것이 더 좋을 것입니다. 이는 올바른 "바디"를 클래스에 설정하고 단위 테스트의 경우 쉽게 모의 객체를 놓을 것입니다. 그러나 그것은 정말로 당신에게 달려 있으며이 프로젝트에서 얼마나 많은 노력이 의미가 있다고 생각하는지.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top