2016-09-03 28 views
5

'a göre, PyCapsule_New() numaralı üçüncü argüman, kapsül yok edildiğinde çağrılması gereken bir yıkıcıyı belirtebilir. Ben nesne örneğini oluşturmak ve ya Python konsolundan çıkmak sildiğinizdeBir PyCapsule nesnesini yok sayma

void mapDestroy(PyObject *capsule) { 

    lash_map_simple_t *map; 
    fprintf(stderr, "Entered destructor\n"); 
    map = (lash_map_simple_t*)PyCapsule_GetPointer(capsule, "MAP_C_API"); 
    if (map == NULL) 
     return; 
    fprintf(stderr, "Destroying map %p\n", map); 
    lashMapSimpleFree(map); 
    free(map); 

} 

static PyObject * mapSimpleInit_func(PyObject *self, PyObject *args) { 

    unsigned int w; 
    unsigned int h; 
    PyObject *pymap; 

    lash_map_simple_t *map = (lash_map_simple_t*)malloc(sizeof(lash_map_simple_t)); 

    pymap = PyCapsule_New((void *)map, "MAP_C_API", mapDestroy); 

    if (!PyArg_ParseTuple(args, "II", &w, &h)) 
     return NULL; 

    lashMapSimpleInit(map, &w, &h); 

    return Py_BuildValue("O", pymap); 

} 

Ancak, yıkıcı çağrılacak görünmüyor:

>>> a = mapSimpleInit(10,20) 
>>> a 
<capsule object "MAP_C_API" at 0x7fcf4959f930> 
>>> del(a) 
>>> a = mapSimpleInit(10,20) 
>>> a 
<capsule object "MAP_C_API" at 0x7fcf495186f0> 
>>> quit() 
[email protected] ~/programming/src/liblashgame $ 

Benim tahminim bir ilgisi olmasıdır Py_BuildValue(), "kapsül" e yeni bir referans döndürerek, silme işleminden sonra orijinali etkilemez. Her neyse, nesnenin düzgün bir şekilde imha edilmesini nasıl sağlarım? (Linux üzerine) Python 3.4.3 [GCC 4.8.4] Kullanılması

cevap

0

Py_BuildValue("O", thingy) sadece thingy için refcount artırmak ve onu geri dönecek - dokümanlar “yeni başvuru” verir ama bu olmadığını söylüyorlar varolan bir PyObject* geçirdiğinizde oldukça doğru.

Bu işlevler - sizin sorunuzdaki, yani - aynı çeviri biriminde tanımlanmışsa, yıkıcı işlevinin muhtemelen static (tam imzasının static void mapDestroy(PyObject* capsule); olması gerekir) olarak bildirilmesi gerekir. Python API'si, yıkıcıyı aramak için zaman geldiğinde fonksiyonların adresini düzgün bir şekilde arayabilir.

… Belleğindeki yıkıcı adresi geçerli olduğu sürece, static işlevini kullanmak zorunda değilsiniz. Örneğin, yakalamayan C++ lambda işlev işaretçilerine dönüştürülebildiğinden, a C++ non-capturing lambda as a destructor'u başarıyla kullandım; Eğer sizin için daha iyi çalışan kapsül yıkıcınız için bir fonksiyon gösterici elde etmek ve kullanmak için başka bir yol kullanmak isterseniz, bunun için her şeyi yapın.