【问题标题】:Access violation in PyRun_String()PyRun_String() 中的访问冲突
【发布时间】:2019-06-10 12:49:26
【问题描述】:

我在调用 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。

提前致谢。

【问题讨论】:

  • 您确定您的访问违规在PyRun_String 中吗?当我运行代码时,它在Py_Finalize 中崩溃。 (由于只有 Python 3.5.2,我不得不将 Py_FinalizeEx 替换为 Py_Finalize。)
  • @rtoijala 可能你是对的。我用 python 2.7 和 PyFinalize 进行了测试,然后我得到的错误是:“致命的 Python 错误:删除实习字符串失败”。我真的不在乎使用 python 2 还是 3。我需要的是摆脱错误。

标签: python c python-c-api


【解决方案1】:

问题是你在不应该破坏sympy 模块的字典的时候。根据documentation for PyModule_GetDict,返回的字典引用是借来的,而不是新的。因此,您不得致电Py_DECREF。删除带有Py_DECREF(pdict); 的行可解决此问题。

更多关于所有权和从Python documentation借款:

所有权也可以转移,这意味着接收引用所有权的代码将负责最终通过在不再需要时调用 Py_DECREF()Py_XDECREF() 或传递此责任(通常给它的调用者)。当一个函数将引用的所有权传递给它的调用者时,调用者就被称为接收到一个新的引用。当没有所有权转移时,调用者被称为借用了引用。借来的参考资料不需要做任何事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多