3

あいまい文字列検索用のカスタム python モジュールがあり、レーベンシュタイン距離計算を実装しています。これには、すべての計算を行う wlevtree C 型 (tree と呼ばれる) へのポインターと PyObject* を指す 2 つのメンバーを持つ levtree と呼ばれる python 型が含まれています。 wordlist と呼ばれる python-strings の python-list。必要なものは次のとおりです。

- levtree の新しいインスタンスを作成するとき、文字列のタプルを唯一の入力として受け取るコンストラクターを使用します (インスタンスがすべての検索を実行する辞書です)。このコンストラクターは、の新しいインスタンスを作成する必要があります。 wordlist を levtree の新しいインスタンスにコピーし、入力タプルの内容を wordlist の新しいインスタンスにコピーします。これが私の最初のコードスニペットと私の最初の質問です:

static int
wlevtree_python_init(wlevtree_wlevtree_obj *self, PyObject *args, PyObject *kwds)
{
    int numLines;       /* how many lines we passed for parsing */
    wchar_t** carg;        /* argument to pass to the C function*/
    unsigned i;

    PyObject * strObj;  /* one string in the list */
    PyObject* intuple;

    /* the O! parses for a Python object (listObj) checked
      to be of type PyList_Type */
    if (!(PyArg_ParseTuple(args, "O!", &PyTuple_Type, &intuple)))
    {
        return -1;
    }

    /* get the number of lines passed to us */
    numLines = PyTuple_Size(intuple);
    carg = malloc(sizeof(char*)*numLines);

    /* should raise an error here. */
    if (numLines < 0)
    {
        return -1; /* Not a list */
    }

    self->wordlist = PyList_New(numLines);
    Py_IncRef(self->wordlist);
    for(i=0; i<numLines; i++)
    {

        strObj = PyTuple_GetItem(intuple, i);
        //PyList_Append(self->wordlist, string);
        PyList_SetItem(self->wordlist, i, strObj);
        Py_IncRef(strObj);
    }

    /* iterate over items of the list, grabbing strings, and parsing
       for numbers */
    for (i=0; i<numLines; i++)
    {

        /* grab the string object from the next element of the list */
        strObj = PyList_GetItem(self->wordlist, i); /* Can't fail */

        /* make it a string */


        if(PyUnicode_Check(strObj))
        {
            carg[i] = PyUnicode_AsUnicode( strObj );
            if(PyErr_Occurred())
            {
                return -1;
            }
        }
        else
        {
            strObj = PyUnicode_FromEncodedObject(strObj,NULL,NULL);
            if(PyErr_Occurred())
            {
                return -1;
            }
            carg[i] = PyUnicode_AsUnicode( strObj );
        }
    }
    self->tree = (wlevtree*) malloc(sizeof(wlevtree));
    wlevtree_init(self->tree,carg,numLines);
    free(carg);
    return 0;
}

Py_IncRef(self->wordlist); を呼び出す必要がありますか? self->wordlist = PyList_New(numLines); の後 または、参照が PyList_new で既にインクリメントされているため、冗長ですか? 次に、 PyList_SetItem(self->wordlist, i, strObj); についても同じ疑問があります。そして Py_IncRef(strObj);..

- levtree のインスタンスを破棄するとき、tree が占有するスペースを解放する C 関数を呼び出し、wordlist を破棄し、wordlist に含まれるすべての文字列のすべての参照カウントをデクリメントします。ここに私の tp_dealloc があります:

static void
wlevtree_dealloc(wlevtree_wlevtree_obj* self)
{
    //wlevtree_clear(self);
    if(self->tree!=NULL)
    {
        wlevtree_free(self->tree);
    }
    free(self->tree);
    PyObject *tmp, *strObj;
    unsigned i;
    int size = PyList_Size(self->wordlist);
    for(i=0; i<size; i++)
    {
        strObj = PyList_GetItem(self->wordlist, i);
        Py_CLEAR(strObj);
    }
    Py_CLEAR(self->wordlist);
    Py_TYPE(self)->tp_free((PyObject *)self);
}

ここですべての割り当て解除を機能させるのは正しいですか? 現時点では tp_clear と tp_free を持っていませんが、必要ですか? 現時点で私のコードは割り当てでは機能しますが、割り当て解除では機能しません。これは、同じ python 変数でinitを複数回呼び出すことができますが、すべての python スクリプトの最後に (これは正しく機能します)、「セグメンテーション フォールト」が発生するためです。割り当て解除プロセスで何かがうまくいかないと思います..

4

1 に答える 1