2016-09-03 9 views
5

documentationによると、PyCapsule_New()の3番目の引数はデストラクタを指定できます。デストラクタはカプセルが破棄されたときに呼び出されるものとします。私は、オブジェクトをインスタンス化し、それやPythonコンソールからの出口を削除すると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); 

} 

しかし、デストラクタが呼び出されていないようです:

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

私の推測では、それはとは何かを持っているということですPy_BuildValue()は「カプセル」への新しい参照を返します。削除は元のものに影響しません。とにかく、オブジェクトが適切に破壊されていることを確認するにはどうすればいいですか? (Linuxの場合)のPython 3.4.3 [GCC 4.8.4]を使用して

答えて

0

Py_BuildValue("O", thingy)だけthingyのための参照カウントをインクリメントし、それを返します - ドキュメントは、それは「新しいリファレンス」を返しますが、それはないと言います既存のPyObject*を渡すときわめて真実です。

これらの機能(質問内の機能)がすべて同じ翻訳単位で定義されている場合、デストラクタ関数はstaticと宣言される必要があります(したがって完全な署名はstatic void mapDestroy(PyObject* capsule);となります)。 Python APIはデストラクタを呼び出すときに関数のアドレスを適切に検索できます。

...メモリ内のデストラクターのアドレスが有効である限り、static関数を使用する必要はありません。例えば、私は首尾よくa C++ non-capturing lambda as a destructorを使用しました。非キャプチャC++ラムダを関数ポインタに変換することができます。カプセルデストラクタの関数ポインタを取得して渡す別の方法を使いたい場合は、是非それを行ってください。

関連する問題