I have two versions of a part of a program. One is written in C and the second one is in Python. The Python version has been developed much more than the C version but a critical function is slow and is already present in C.
Therefore I want to wrap the C-version using the C-Python API and import it in Python to improve the speed
But I don’t know how to parse objects from a class defined in Python, inside the C function.
The two classes defined in Python have many attributes:
class Py_input: #it will store the input data def__init__(self): selt.n1 = ... self.n2 = ... self.n3 = ... . . . class Py_output: #it will store the output data def __init__(self): self.out1 = np.zeros(...) self.out2 = np.zeros(...) . . .
The function receives as input an object of py_input and stores the outputs in an object of py_output. I need to pass those objects to a C extension of Python written using the C – API such as in the example:
import c_fun inp = Py_input() out = Py_output() c_fun.function(inp, out)
where the c_fun.so module has been generated by compiling the C code using GCC:
gcc -I/usr/include/Python3.8/ -shared -o c_fun.so -fPIC c_fun.c
In C all the attributes of the python classes are stored in structs.
The best solution I believe should be to parse the object inside the C code into the C-struct. My issue is that I don’t know how to parse a Python-generated class.
I have tried using PyObject_GetAttrString to parse the objects but I get an error. When I looked for the attribute using PyObject_HasAttrString
it returns that there is no element named “n1”.
such as:
static PyObject* py_function(PyObject* self, PyObject* args) { PyObject obj_in, obj_out; if (!PyArg_ParseTuple(args, "OO", &obj_in, & obj_out)) return NULL; int a = PyObject_HasAttrString(&obj_in, "n1"); // it returns 0 so False . . . }
Some other solutions that I have thought of: I unpack the class. such as:
c_fun.function(inp.n1, inp.n2, inp.n3,..., out.out1,...)
But that could risk having a confusing function and I could easily make errors.
I could create two custom Python types in C but that would mean adding a third copy of the same struct being the other two already integrated
Advertisement
Answer
The issue was PyObject obj_in, obj_out;
it should have been a pointer.
PyObject *obj_in; PyObject *obj_out;
After fixing the pointers, PyObject_HasAttrString
and PyObject_GetAttrString
work fine.