2

I am importing a shared object library written in C and calling to some wrapper functions I made that work using the Python.h library.

I have a function with the following prototype:

PyObject *Cal_readFile( PyObject *self, PyObject *args );

I parse out the following tuples:

PyArg_ParseTuple(args, "sO", &filename, &result)

From python the call looks like this:

result = []
status = Cal.readFile(filename, result)
print(result)

It is called fine, and the function definitely runs. My goal is to modify that result variable within the C function that is called. And that is exactly what I do. I modify the result variable within the C function and am using result = Py_BuildValue("[lO]", (long)comp, compList); to put new data into it.

However when I then print result in Python I still have the same empty list I started with.

Is there some additional step I need to do to modify this python variable from the C function? I cannot use it in the return as you already see that I am collecting a return status from there (this return works).

Edit: Some code from readCal that may be useful:

PyObject *result = NULL;
PyArg_ParseTuple(args, "sO", &filename, &result);
//Some creating of data is done, and then I am trying to set the list to that data:

result = Py_BuildValue("[lO]", (long)comp, compList);
ComputerLocus
  • 3,448
  • 10
  • 47
  • 96

2 Answers2

2

You cannot replace the result altogether, but you can append values to it, or remove existing values and so forth. Something like this could do what you'd need:

if (!PyArg_ParseTuple(args, "sO", &filename, &result)) {
    return NULL;
}

PyObject *l = PyLong_FromLong((long)comp);
if (!l) {
    return NULL;
}

int success = PyList_Append(result, l);
Py_DECREF(l);
if (! success) {
    return NULL;
}

success = PyList_Append(result, complist);
if (! success) {
    return NULL;
}
1

When you do:

PyArg_ParseTuple(args, "sO", &filename, &result)

you're assigning an instance reference as handled by python into the result pointer.

Then when you do:

result = Py_BuildValue("[lO]", (long)comp, compList);

you're replacing the value referenced by the result pointer by a new one. Meaning that within your python code, the result variable still points to the former instance.

If you want to modify the pointed list instance, then you shall use the List methods in C, to mutate the instance itself, instead of creating a new instance.

Basically, what you do in your C code, is the same as the following python code:

>>> def foo(result):
...    result = [4,5,6]
...
>>> result = [1,2,3]
>>> foo(result)
>>> print(result)
[1,2,3]

what you'd want is to do — in python — is:

>>> def foo(result):
...    while len(result): 
...        result.pop() # or any operation that mutates the result instance
...    result += [4,5,6]
...
>>> result = [1,2,3]
>>> foo(result)
>>> print(result)
[4,5,6]

now I leave it up to you to do it using the C API ;-)

HTH

zmo
  • 24,463
  • 4
  • 54
  • 90