为什么PyGILState_Release引发致命的Python错误 - c++

ANSWERED

好的,我解决了这个问题。这全在于您如何初始化线程状态。您根本不需要使用ReleaseLock。只需将InitThreads调用添加到模块定义即可:

BOOST_PYTHON_MODULE(ModuleName)
{
    PyEval_InitThreads();

    ...
}

好的,我已经尝试了数小时来诊断此问题,并仔细阅读了网上的每个示例。现在累了,所以我可能会遗漏一些明显的东西,但这是发生了什么:

我在boost Python中包装一个库。我正在运行一个python脚本,该脚本导入lib,构造一些对象,然后接收来自c ++的回调,该回调调用python。在调用任何python函数之前,我尝试获取全局解释器锁。这是一些示例代码:

class ScopedGILRelease
{
public:
   inline ScopedGILRelease()
   {
      d_gstate = PyGILState_Ensure();
   }

   inline ~ScopedGILRelease()
   {
      PyGILState_Release(d_gstate);
   }

private:
   PyGILState_STATE  d_gstate;
};

class PyTarget : public DingoClient::ClientRequest::Target, public wrapper<DingoClient::ClientRequest::Target>
{
  public:
    PyTarget(PyObject* self_) : self(self_) {}
    ~PyTarget() {
      ScopedGILRelease gil_lock;
    }
    PyObject* self;

    void onData(const boost::shared_ptr<Datum>::P & data, const void * closure)
    {
       ScopedGILRelease gil_lock;
       // invoke call_method to python 
    }

    ...
}

库将Target对象上的onData方法作为回调调用。在python中,我们继承自PyTarget并实现了另一个方法。然后,我们使用call_method 调用该方法。 gil_lock获取锁,并通过RIAA保证获取的线程状态始终是一个发行版,并且实际上在超出范围时总是被释放。

但是,当我在试图获取此函数大量回调的脚本中运行此脚本时,它始终会出现段错误。脚本看起来像这样:

# Initialize the library and setup callbacks
...

# Wait until user breaks
while 1:
  pass

另外,python脚本总是构造一个运行的对象:

PyEval_InitThreads();
PyEval_ReleaseLock();

在收到任何回调之前。

我将代码减少到什至在onData中甚至没有调用python的地方,我只是获得了锁。发行时,总是崩溃,其中之一:

Fatal Python error: ceval: tstate mix-up
Fatal Python error: This thread state must be current when releasing

要么

Fatal Python error: ceval: orphan tstate
Fatal Python error: This thread state must be current when releasing

看来是随机的。我在这里疯了吗,因为我觉得我正确使用了GIL锁,但是它似乎根本不起作用。

其他说明:
只有一个线程曾经调用过该Target对象的onData方法。

当我使用time.sleep()在调用python模块的while循环中睡眠时,似乎允许脚本运行更长的时间,但最终脚本将出现类似问题的段错误。它持续的时间长短与time.sleep(即time.sleep(10)运行的时间长于time.sleep(0.01))成正比。这让我想到了一些未经我允许的脚本如何重新获取GIL 。

PyGILState_Release和PyGILState_Ensure在我的代码中的其他地方都没有调用,也没有其他地方应该在python中调用。

更新

我读过另一个问题,建议在模块中导入线程作为运行的替代方法

PyEval_InitThreads();
PyEval_ReleaseLock();

但是,当我在模块之前导入线程并从boost python包装器中删除以上两行时,它似乎不起作用。

参考方案

好的,我解决了这个问题。这全在于您如何初始化线程状态。您根本不需要使用ReleaseLock。只需将InitThreads调用添加到模块定义即可:

BOOST_PYTHON_MODULE(ModuleName)
{
    PyEval_InitThreads();

    ...
}

在Java中,执行“ ++++++++”表达式,编译器未报告任何错误并且可以正确执行? - java

我用eclipse编写了这段代码,用war写过,结果为3d。public static void main(String[] args) { double a = 5d + + + + + +-+3d; System.out.println(a); } 参考方案 您的表情可以改写为(5d) + (+ + + + +-+3d) 其中第一个+是应用于两个操作数的…

将Python嵌入C++应用程序 - c++

上下文:我们一直面临的一个持续问题是对我们的市场数据应用程序进行单元测试。这些应用程序坐下来观察从提要中检索到的数据并执行某些操作。一些很难触发的关键事件很少发生,并且测试人员很难在所有情况下验证我们的应用程序是否正常运行,因此我们必须依靠单元测试。这些系统通常通过在事件发生时发出回调(进入我们的应用程序)来工作,然后由我们负责处理此事件。 我设想的解决方案…

在Python和C++之间传输数据而无需写入Windows和Unix文件 - python

我有预先存在的python和C ++文件,其中python文件定义了许多点,而C ++代码利用其现有库进行了所需的计算。最终产品是C ++代码写入的文件。我正在寻找一种在python中获取2000点列表的方法,将其传递给函数,然后执行所有C ++代码并输出我需要的文件。其他注意事项。这必须是可以在Linux或Windows机器上工作的东西,并且最少安装新插件…

扩展Python时可以使用C++功能吗? - c++

Python手册说您可以在C和C++中为Python创建模块。使用C++时可以利用类和模板之类的东西吗?它不会与其他库和解释器产生不兼容吗? 参考方案 挂钩函数的实现是用C还是用C++实现都没有关系。实际上,我已经看过一些Python扩展,这些扩展有效利用C++模板甚至Boost库。没问题。 :-)

Python的C++名称处理库 - c++

Improve this question 我想在Python程序中修改和分解C++函数名。有没有类似的东西可用?我搜索了几个小时,也许我很幸运在这里... 参考方案 您很可能不想在Python中执行此操作。顺便说一句,您可能不应该从DLL中导出错误的名称,因为这样会使具有不同编译器的人难以使用。如果必须使用变形的名称,则只需在Python代码中对其进行硬编…