Reference counting problems?

Eric Frederich eric.frederich at gmail.com
Thu Dec 9 15:23:40 EST 2010


I am attempting to automate the building of binding for a 3rd party library.
The functions I'm wrapping all return an integer of whether they
failed and output are passed as pointers.
There can be multiple return values.
So the code that I generate has a PyObject* called python__return_val
that I use for returning.
In the 'wrapped_foo' function below you see I build the return value
with Py_BuildValue and "OO" as the format.
For every output I have I do a C to Python conversion and add another
'O' to the format.
What I'm wondering is if I can use the same logic when wrapping
functions that only return one value like the wrapped_bar function
below.

So for multiples, I wind up doing this which is fine.

    python__x = Py_BuildValue("s", x)
    python__y = Py_BuildValue("s", y)
    python__return_val = Py_BuildValue("OO", python__x, python__y);

But for single returns I do something like this....
I realize that the 2 lines below are pointless, but are they causing a
memory leak or problems with reference counting?

    python__x = Py_BuildValue("s", x)
    python__return_val = Py_BuildValue("O", python__x);


Are python__x and python__return_val the same object, a copy of the object?
Would python__x ever get garbage collected?
Should my code generator detect when there is only one output and not
go through the extra step?

Thanks,
~Eric



static PyObject *
wrapped_foo(PyObject *self, PyObject *args)
{
    int wrapp_fail;
    // C types
    int                  x;
    const char*          some_str;
    int*                 y;
    char**               abc;

    // Python types
    PyObject*            python__return_val;
    PyObject*            python__y;
    PyObject*            python__abc;

    // Get Python args
    if (!PyArg_ParseTuple(args, "is", &x, &some_str))
        return NULL;

    // Wrapped Call
    wrapp_fail = foo(x, some_str, &y, &abc);
    if(wrapp_fail != 0){
        return NULL;
    }

    // Convert output to Python types
    python__y = Py_BuildValue("i", y)
    python__abc = Py_BuildValue("s", abc)


    // Build Python return value
    python__return_val = Py_BuildValue("OO", python__y, python__abc);

    // Memory free's
    MEM_free(abc)

    return python__return_val;
}


static PyObject *
wrapped_bar(PyObject *self, PyObject *args)
{
    int wrapp_fail;
    // C types
    int                  a;
    const char*          b;
    char**               c;

    // Python types
    PyObject*            python__return_val;
    PyObject*            python__c;

    // Get Python args
    if (!PyArg_ParseTuple(args, "is", &a, &b))
        return NULL;

    // Wrapped Call
    wrapp_fail = bar(a, b, &c);
    if(wrapp_fail != 0){
        return NULL;
    }

    // Convert output to Python types
    python__c = Py_BuildValue("s", c)


    // Build Python return value
    python__return_val = Py_BuildValue("O", python__c);

    // Memory free's
    MEM_free(c)

    return python__return_val;
}



More information about the Python-list mailing list