仅仅是为了它,我决定创建一个Scheme binding to libpython,这样你就可以在Scheme程序中嵌入Python。我已经能够调用Python的C API,但我还没有真正考虑过内存管理。
mzscheme的FFI工作方式是我可以调用一个函数,如果该函数返回指向PyObject
的指针,那么我可以自动增加引用计数。然后,我可以注册一个终结器,当Scheme对象被垃圾收集时,它会减少引用计数。我看了documentation for reference counting,乍看之下没有看到任何问题(尽管在某些情况下它可能不是最佳的)。我有什么陷阱吗?
另外,我在制作cyclic garbage collector documentation的正面或尾部时遇到了麻烦。我需要记住哪些事情?特别是,我如何让Python意识到我有一些东西的引用,所以当我还在使用它时它不会收集它?
答案 0 :(得分:7)
您指向http://docs.python.org/extending/extending.html#reference-counts的链接是正确的位置。文档的扩展和嵌入以及Python / C API部分将解释如何使用C API。
引用计数是使用C API的烦人部分之一。主要问题是保持一切:根据您调用的API函数,您可能拥有或不拥有对所获得对象的引用。要小心了解你是否拥有它(因此不能忘记将其删除或将其交给可以窃取它的东西)或借用它(并且必须包含它以保留它并可能在你的函数中使用它)。涉及此问题的最常见错误是1)错误地记住您是否拥有特定函数返回的引用; 2)相信您可以安全地借用引用的时间比您更长。
您不必为循环垃圾收集器执行任何特殊操作。只是在那里修补引用计数中的缺陷并且不需要直接访问。
答案 1 :(得分:3)
我知道最重要的问题是引用计数和C API是__del__
的事情。当你借用某个东西时,你认为你可以在没有INCREF的情况下逃脱,因为你在使用该引用时不会放弃GIL。但是,如果您最终删除某个对象(例如,将其从列表中删除),则可能会触发__del__
调用,这可能会删除您从脚下借来的引用。非常棘手。
如果您获得所有借用的引用(当然,然后是DECREF),那么应该没有任何问题。