【问题标题】:Call Python from C++从 C++ 调用 Python
【发布时间】:2009-09-13 11:04:48
【问题描述】:

我正在尝试从我的主 C++ 程序调用 Python 脚本中的函数。 python 函数接受一个字符串作为参数并且不返回任何内容(ok.. 'None')。 只要在再次调用函数之前完成之前的调用,它就可以很好地工作(从未想过会那么容易..),否则在pModule = PyImport_Import(pName)会出现访问冲突。

有很多教程如何在 C 中嵌入 python,反之亦然,但我没有发现任何关于这个问题的内容。

int callPython(TCHAR* title){
    PyObject *pName, *pModule, *pFunc;
    PyObject *pArgs, *pValue;

Py_Initialize();
    pName = PyUnicode_FromString("Main");
    /* Name of Pythonfile */

    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

if (pModule != NULL) {
        pFunc = PyObject_GetAttrString(pModule, "writeLyricToFile");
        /* function name. pFunc is a new reference */
        if (pFunc && PyCallable_Check(pFunc)) {
            pArgs = PyTuple_New(1);

    pValue = PyUnicode_FromWideChar(title, -1);

    if (!pValue) {
        Py_DECREF(pArgs);
                Py_DECREF(pModule);
        showErrorBox(_T("pValue is false"));
        return 1;
            }
    PyTuple_SetItem(pArgs, 0, pValue);

            pValue = PyObject_CallObject(pFunc, pArgs);
            Py_DECREF(pArgs);

            if (pValue != NULL) {
                //worked as it should!
                Py_DECREF(pValue);
            }
            else {
                Py_DECREF(pFunc);
                Py_DECREF(pModule);
                PyErr_Print();
        showErrorBox(_T("pValue is null"));
        return 1;
            }
        }
        else {
            if (PyErr_Occurred()) PyErr_Print();
            showErrorBox(_T("pFunc null or not callable"));
        return 1;
        }
        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    }
    else {
        PyErr_Print();
        showErrorBox(_T("pModule is null"));
    return 1;
    }
    Py_Finalize();
    return 0;
}

【问题讨论】:

    标签: c++ python c


    【解决方案1】:

    当您说“只要在再次调用函数之前完成上一次调用”时,我只能假设您有多个线程从 C++ 调用到 Python。 python不是线程安全的,所以这会失败!

    阅读 Python 手册中的全局解释器锁 (GIL)。也许以下链接会有所帮助:

    维基百科上提到了 GIL:

    【讨论】:

      【解决方案2】:

      感谢您的帮助!

      是的,你是对的,有几个 C 线程。从没想过解释器本身需要互斥锁 - GIL 对我来说是一个全新的概念(甚至在整个教程中都没有提到)。

      在阅读参考资料后(肯定不是其中最简单的部分,虽然 PyGILState_* 函数大大简化了整个事情),我添加了一个

      void initPython(){
          PyEval_InitThreads();
          Py_Initialize();
          PyEval_ReleaseLock();
      }
      

      函数来正确初始化解释器。 每个线程都创建自己的数据结构,获取锁并在之后释放它,如参考中所示。

      正常工作,但是在终止进程之前调用 Py_Finalize() 时,我得到一个段错误.. 离开它有什么问题吗?

      【讨论】:

      • 很高兴这解决了您的问题。我想不出为什么你会在调用 Py_Finalize() 时遇到问题——也许你可以提供一个简化的例子来显示另一个问题中的问题。你真的应该彻底关闭 Python,但如果你只是要退出应用程序,你可能会没事......我强烈建议你找出它崩溃的原因。
      • @DanielPaull 能否为上述相同主题提供一个简单的工作示例。所以我很容易理解
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-07
      • 2011-11-14
      • 1970-01-01
      • 2023-04-03
      • 2013-08-30
      • 2023-03-25
      • 1970-01-01
      相关资源
      最近更新 更多