6

Sadece onun içindeyse, bir Python'u Scheme programlarına yerleştirebilmeniz için bir Scheme binding to libpython oluşturmaya karar verdim. Python'un C API'sine zaten çağrı yapabilirim, ancak bellek yönetimini gerçekten düşünmedim.C kodu ile uğraşırken Python referans sayım/çöp toplama hasadı var mı?

mzscheme'nin FFI çalışma biçimleri, bir işlevi çağırabilmem ve bu işlev PyObject işaretçisini döndürürse, otomatik olarak referans sayımını artırabilir. Daha sonra, Scheme nesnesi çöp toplandığında, referans sayımını azaltacak bir finalizer kaydedebilirim. documentation for reference counting'a baktım ve ilk bakışta bununla ilgili herhangi bir sorun görmüyorum (bazı durumlarda alt-optimal olsa da). Kaybettiğim herhangi bir yaka var mı?

Ayrıca, cyclic garbage collector documentation'un başlıklarını veya kuyruklarını oluşturmada sorun yaşıyorum. Burada akılda tutulması gereken şeyler neler? Özellikle, Python'u bir şeye referans olduğumu bilmesini nasıl sağlarım?

cevap

7

Adres http://docs.python.org/extending/extending.html#reference-counts adresiniz için doğru adres. Belgenin Genişletme ve Katıştırma ve Python/C API bölümleri C API'sini nasıl kullanacağınızı açıklayan bölümlerdir.

Referans sayımı, C API'sinin kullanılmasının rahatsız edici kısımlarından biridir. Ana kazanç her şeyi düz tutuyor: Aradığın API işlevine bağlı olarak, aldığınız nesneye ait referansın sahibi olabilir veya olmayabilir. Kendinize ait olup olmadığınızı anlamaya dikkat edin (ve bundan vazgeçmeyeceğinizi ya da bunu çalacak bir şeyi vermeyi unutmayın) veya ödünç almayı unutmayın (ve bunu devam ettirmek için INCREF ve bunu fonksiyonunuzda kullanmanız gerekir). Bunu içeren en yaygın hatalar 1) belirli bir işlev tarafından döndürülen bir referansa sahip olup olmadığınızı yanlış olarak hatırlamaktır ve 2) referansı sizden daha uzun bir süre boyunca ödünç almak için güvenli olduğunuzu düşünmek.

Döngüsel çöp toplayıcı için özel bir şey yapmak zorunda değilsiniz. Sadece referans sayımında bir kusuru düzeltmek için var ve doğrudan erişim gerektirmiyor.

+0

Python, döngüsel yapı için referans sayma * ve * çöp toplayıcısını kullanıyor? Bu oldukça büyük bir kusur. Tasarım türü. Her durumda, bu, bir python tarafındaki döngüye katılan herhangi bir değerin şemaya maruz kalması durumunda, Jason için işleri "daha eğlenceli" hale getirecek gibi görünüyor. –

+0

İyi bilgi. Elime geçtiğimde herşeyi INCREF ve işimi bitirdiğimde herşeyi DECREF ettiğimde, tamam mıyım? Yoksa karşılaşabileceğim herhangi bir sorun var mı? –

+2

@Jason, sadece INCREF * ödünç alındı ​​* referanslar. Bazı işlevler halihazırda INCREF olan * yeni * referansları döndürür. INCREF'ing onları bir bellek sızıntısına neden olur. –

3

Ref sayma ve C API ile bildiğim en büyük gotcha __del__ şeydir. Bir şey için ödünç alınmış bir referansınız olduğunda, bu referansı kullanırken GIL'den vazgeçmediğiniz için INCREF'ing olmadan uzaklaşabileceğinizi düşünüyorsunuz. Ancak, bir nesneyi silmeyi bitirirseniz (örneğin, bir listeden kaldırarak), __del__ numaralı çağrıyı tetiklemeniz mümkündür; bu da, ödünç aldığınız referansı ayaklarınızın altından kaldırabilir. Çok zor.

INCREF (ve sonra DECREF, elbette) tüm ödünç alınan referansları alır almaz, herhangi bir sorun olmamalıdır.