我有一些ctypes绑定,并为每一个体。新的我应该叫体。免费的。图书馆我要结合不必分配程序的绝缘出的其余部分的代码(他们可以被称为有关的任何地方存在),并使用几个有用的功能我需要循环的参考。

我认为这将会解决如果我找到一个可靠的方式挂钩析构的一个对象。(weakrefs会的帮助,如果他们想让我只是回调 之前 数据是下降了。

所以很明显这个代码megafails当我把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)

我还试图解决它通过weakrefs,与那些东西似乎越来越只是更糟的是,仅仅在很大程度上更加不可预测。

甚至如果我不把在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

如果weakrefs未破,我想这可能工作:

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不会处理,我应该与绑定释放空闲内存这应该工作。是的,这basicly一个黑客,但我认为这可能比以前的事情,我一直在努力更好地工作。

编辑:试了一下,似乎小后上班微调我的代码。一个令人惊讶的事情是,即使我的删除出从我所有的结构,它似乎仍然会失败。有趣的,但令人沮丧。

无论是作品,从一些怪异的机会,我已经能够在地方离席循环引用,但事情留破产了。

编辑:嗯.. weakrefs WERE毕竟碎了!所以有可能对于在python可靠清理无解,除了不是迫使它是显式的。

其他提示

你想要做什么,那就是创建一个分配的事情,然后当对象不再使用自动重新分配,是几乎不可能在Python的对象,很遗憾。在删除声明不能保证被调用,所以你不能依靠这一点。

在Python的标准方法是简单地:

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

或者因为2.5还可以创建上下文管理者和with语句,这是这样做的一个更合适的方法使用。

但是这两种主要当你在一个代码段的开始分配/锁。如果你想有分配方案的整个运行的东西,你需要在启动时分配的资源,该方案的主要代码运行之前,事后解除分配。还有这里没有涉及一种情况,那就是当你想分配和动态解除分配的资源,并在代码中的许多地方使用它们。例如你想要的内存缓冲区或类似的游泳池。但大多数的情况下是内存,Python会为你处理,所以你不必理会那些。还有的地方,你想拥有的东西,不是动态内存池分配过程的情况下,然后你会希望你在你的例子尝试释放的类型,而的棘手与Python做

在CPython, __del__ 一个可靠析构的对象,因为它总是会被称为当参考数达到零(注:有可能的情况下-喜欢圆形引用的项目 __del__ 定义的方法-这里的参数将永远不会达到零,但这是另外一个问题)。

更新 从评论,我理解这个问题有关的是为破坏对象: 身体 是一个全球性的目的,及正在销毁之前,所有其他目的,因此它不再是提供给他们。
实际上,采用全球对象不好;这不仅是因为问题这样的一个,而且还因为维护。

然后我会改变你的类的东西喜欢这个

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