PyRun_String()中的访问冲突

时间:2019-06-10 12:49:26

标签: python c python-c-api

我在调用Python的C代码中遇到访问冲突错误。

我正在尝试从Python调用sympy函数并在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;
}

我想知道这种访问冲突的原因以及如何解决。我也想知道为什么注释后的printf不能显示结果。

我的编译行是:

gcc probe.c `python3-config --cflags` `python3-config --ldflags` -fpic

我的Python版本是3.6.7。

谢谢。

1 个答案:

答案 0 :(得分:2)

问题是您不应该破坏sympy模块的字典。根据{{​​3}},返回的字典参考是借来的,不是新的。因此,您不能在其上调用Py_DECREF。删除带有Py_DECREF(pdict);的行可解决此问题。

有关所有权和从documentation for PyModule_GetDict借用的更多信息:

  

所有权也可以转移,这意味着接收引用所有权的代码随后负责通过在不再需要时调用Py_DECREF()Py_XDECREF()或继续传递来最终对其进行拒绝引用这种责任(通常是对它的呼叫者)。当函数将引用的所有权传递给其调用方时,该调用方被称为接收新的引用。如果没有所有权转移,则称调用者借用了引用。不需要做任何借用的参考。