2016-09-03 12 views
5

Zgodnie z documentation, trzeci argument do PyCapsule_New() może określać destruktor, który, jak przypuszczam, powinien zostać wywołany podczas niszczenia kapsuły.Niszczenie obiektu PyCapsule

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); 

} 

Jednak, kiedy instancję obiektu i usunąć go lub wyjście z konsoli Pythona, destruktor nie wydaje się nazywać:

>>> 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 $ 

Domyślam się, że to ma coś wspólnego z Py_BuildValue() powraca nowe odniesienie do "kapsuły", która po usunięciu nie wpływa na oryginał. W każdym razie, jak miałbym zadbać o to, aby obiekt został właściwie zniszczony?

Korzystanie Python 3.4.3 [GCC 4.8.4] (na linux)

Odpowiedz

0

Py_BuildValue("O", thingy) po prostu zwiększamy RefCount dla thingy i odesłać go - docs powiedzieć, że zwraca się „nowy odnośnik”, ale to nie jest całkiem prawdziwe, gdy przekazujesz mu istniejący PyObject*.

Jeśli te twoje funkcje - te w twoim pytaniu, które są - są zdefiniowane w tej samej jednostce tłumaczeniowej, funkcja destruktora prawdopodobnie będzie musiała zostać zadeklarowana jako static (aby jej pełny podpis był static void mapDestroy(PyObject* capsule);), aby zapewnić, że API Pythona może poprawnie wyszukać adres funkcji, gdy przychodzi czas wywołania destruktora.

... Nie musisz używać funkcji static, o ile adres destruktora w pamięci jest prawidłowy. Na przykład pomyślnie zastosowałem a C++ non-capturing lambda as a destructor, ponieważ niezapisujące lambdy C++ można przekonwertować na wskaźniki funkcji; jeśli chcesz użyć innego sposobu na uzyskanie i przekazanie wskaźnika funkcji dla destruktora kapsułki, który działa lepiej dla ciebie, na wszelki wypadek, idź do niego.

Powiązane problemy