I've got an access violation error in a C code calling Python.
I am trying to call a sympy function from Python and handle the result in C.
#include <Python.h>
int main(int argc, char *argv[])
{
PyObject *pmod, *pdict, *pValue;
Py_Initialize();
pmod = PyImport_ImportModule("sympy");
PyErr_Print();
pdict = PyModule_GetDict(pmod);
pValue = PyRun_String("x = symbols('x'); diff(cos(x), x)", Py_single_input, pdict, pdict);
PyErr_Print();
if (pValue != NULL) {
//PyObject* pu = PyUnicode_AsEncodedString(pValue, "utf-8", "~E~");
//printf("Result of call: %s\n", PyBytes_AS_STRING(pu));
//Py_DECREF(pu);
Py_DECREF(pValue);
Py_DECREF(pmod);
Py_DECREF(pdict);
}
else {
PyErr_Print();
return 1;
}
Py_FinalizeEx();
return 0;
}
I would like to know the reason for this access violation and how to solve it. I would also like to know why the commented printf to show the result is not working.
My compilation line is:
gcc probe.c `python3-config --cflags` `python3-config --ldflags` -fpic
My Python version is 3.6.7.
Thanks in advance.
The problem is that you are destroying the sympy
module's dictionary when you should not be. According to the documentation for PyModule_GetDict
, the returned dictionary reference is borrowed, not new. Therefore you must not call Py_DECREF
on it. Removing the line with Py_DECREF(pdict);
fixes the issue.
More about ownership and borrowing from the Python documentation:
Ownership can also be transferred, meaning that the code that receives ownership of the reference then becomes responsible for eventually decref’ing it by calling
Py_DECREF()
orPy_XDECREF()
when it’s no longer needed—or passing on this responsibility (usually to its caller). When a function passes ownership of a reference on to its caller, the caller is said to receive a new reference. When no ownership is transferred, the caller is said to borrow the reference. Nothing needs to be done for a borrowed reference.