<bdo id='BSljY'></bdo><ul id='BSljY'></ul>

<small id='BSljY'></small><noframes id='BSljY'>

<i id='BSljY'><tr id='BSljY'><dt id='BSljY'><q id='BSljY'><span id='BSljY'><b id='BSljY'><form id='BSljY'><ins id='BSljY'></ins><ul id='BSljY'></ul><sub id='BSljY'></sub></form><legend id='BSljY'></legend><bdo id='BSljY'><pre id='BSljY'><center id='BSljY'></center></pre></bdo></b><th id='BSljY'></th></span></q></dt></tr></i><div id='BSljY'><tfoot id='BSljY'></tfoot><dl id='BSljY'><fieldset id='BSljY'></fieldset></dl></div>
  • <tfoot id='BSljY'></tfoot>

    1. <legend id='BSljY'><style id='BSljY'><dir id='BSljY'><q id='BSljY'></q></dir></style></legend>

        从 C++(或 C)回调调用 python 方法

        时间:2023-10-17
      1. <legend id='kTabE'><style id='kTabE'><dir id='kTabE'><q id='kTabE'></q></dir></style></legend>
          <tbody id='kTabE'></tbody>

          <tfoot id='kTabE'></tfoot>

            1. <small id='kTabE'></small><noframes id='kTabE'>

                  <bdo id='kTabE'></bdo><ul id='kTabE'></ul>
                  <i id='kTabE'><tr id='kTabE'><dt id='kTabE'><q id='kTabE'><span id='kTabE'><b id='kTabE'><form id='kTabE'><ins id='kTabE'></ins><ul id='kTabE'></ul><sub id='kTabE'></sub></form><legend id='kTabE'></legend><bdo id='kTabE'><pre id='kTabE'><center id='kTabE'></center></pre></bdo></b><th id='kTabE'></th></span></q></dt></tr></i><div id='kTabE'><tfoot id='kTabE'></tfoot><dl id='kTabE'><fieldset id='kTabE'></fieldset></dl></div>
                  本文介绍了从 C++(或 C)回调调用 python 方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  我正在尝试从 C++ 调用 python 类中的方法.调用 this 的 C++ 方法是 C++ 回调.

                  I am trying to call methods in a python class from C++. The C++ method from which this is called is a C++ callback.

                  在这个方法中,当我尝试调用 python 方法时,它给出了segmentation fault.

                  Within this method when I am trying to call python method, it was giving segmentation fault.

                  我已经在一个全局变量中保存了一个 python 函数的实例,比如

                  I have saved an instance of python function in a global variable like

                  // (pFunc is global variable of type PyObject*)
                  pFunc = PyDict_GetItemString(pDict, "PlxMsgWrapper");
                  

                  其中 PlxMsgWrapper 是一个 Python 方法,将在回调中使用.

                  where PlxMsgWrapper is a python method, which will be used in the callback.

                  在回调中,参数被创建为

                  In the callback, the arguments are created as

                  PyObject* args = PyTuple_Pack(2, PyString_FromString(header.c_str()),
                                                   PyString_FromString(payload.c_str()));
                  

                  创建时

                  PyObject * pInstance = PyObject_CallObject(pFunc, args);
                  

                  在这一行中,它给出了分段错误.在此之后,实际的python 方法被称为

                  In this line its giving segmentation fault. After this the actual python method is called as

                  PyObject* recv_msg_func = PyObject_GetAttrString(module, (char *)"recvCallback");
                  args = PyTuple_Pack(1, pInstance);
                  PyObject_CallObject(recv_msg_func, args);
                  

                  推荐答案

                  如果要从 C/C++ 回调调用 Python 函数,则需要做一些事情.首先,当你保存你的 python 函数对象时,你需要增加引用计数:

                  There are a few things you need to do if you are invoking a Python function from a C/C++ callback. First when you save off your python function object, you need to increment the reference count with:

                  Py_INCREF(pFunc)
                  

                  否则 Python 不知道您正在持有一个对象引用,它可能会对其进行垃圾回收,从而在您尝试从回调中使用它时导致分段错误.

                  Otherwise Python has no idea you are holding onto an object reference, and it may garbage collect it, resulting in a segmentation fault when you try to use it from your callback.

                  那么接下来您需要关心的是当您的 C/C++ 回调被调用时正在运行的线程.如果您从另一个非 Python 创建的线程(即在套接字上接收数据的 C/C++ 线程)回调,那么您必须在调用任何 Python API 之前获取 Python 的全局解释器锁 (GIL)职能.否则你的程序的行为是未定义的.要获得 GIL,您可以:

                  Then next thing you need to be concerned about is what thread is running when your C/C++ callback is invoked. If you are getting called back from another non-Python created thread (i.e. a C/C++ thread receiving data on a socket), then you MUST acquire Python's Global Interpreter Lock (GIL) before calling any Python API functions. Otherwise your program's behavior is undefined. To acquire the GIL you do:

                  void callback() {
                      PyGILState_STATE gstate;
                      gstate = PyGILState_Ensure();
                  
                      // Get args, etc.
                  
                      // Call your Python function object
                      PyObject * pInstance = PyObject_CallObject(pFunc, args);
                  
                      // Do any other needed Python API operations
                  
                      // Release the thread. No Python API allowed beyond this point.
                      PyGILState_Release(gstate);
                  }
                  

                  此外,在您的扩展模块的 init 函数中,您应该执行以下操作以确保正确初始化线程:

                  Also, in your extension module's init function, you should do the following to ensure that threading is properly initialized:

                  // Make sure the GIL has been created since we need to acquire it in our
                  // callback to safely call into the python application.
                  if (! PyEval_ThreadsInitialized()) {
                      PyEval_InitThreads();
                  }
                  

                  否则,当您尝试从非 Python 线程获取 GIL 时,可能会发生崩溃和奇怪的行为.

                  Otherwise, crashes and strange behavior may ensue when you attempt to acquire the GIL from a non-Python thread.

                  参见 非-Python 创建线程了解更多详情.

                  这篇关于从 C++(或 C)回调调用 python 方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  上一篇:优点 &amp;回调(std::function/std::bind)与接口(抽象类)的缺点 下一篇:C++ 如何使用 std::bind/std::function 引用模板函数

                  相关文章

                  <small id='RyG9n'></small><noframes id='RyG9n'>

                    <bdo id='RyG9n'></bdo><ul id='RyG9n'></ul>

                  <legend id='RyG9n'><style id='RyG9n'><dir id='RyG9n'><q id='RyG9n'></q></dir></style></legend>

                    <tfoot id='RyG9n'></tfoot>
                    1. <i id='RyG9n'><tr id='RyG9n'><dt id='RyG9n'><q id='RyG9n'><span id='RyG9n'><b id='RyG9n'><form id='RyG9n'><ins id='RyG9n'></ins><ul id='RyG9n'></ul><sub id='RyG9n'></sub></form><legend id='RyG9n'></legend><bdo id='RyG9n'><pre id='RyG9n'><center id='RyG9n'></center></pre></bdo></b><th id='RyG9n'></th></span></q></dt></tr></i><div id='RyG9n'><tfoot id='RyG9n'></tfoot><dl id='RyG9n'><fieldset id='RyG9n'></fieldset></dl></div>