在 C++ 代码中发布 Python GIL
Posted
技术标签:
【中文标题】在 C++ 代码中发布 Python GIL【英文标题】:Releasing Python GIL while in C++ code 【发布时间】:2009-10-16 08:07:48 【问题描述】:我有一个用 C++ 编写的库,我使用 SWIG 包装并在 python 中使用。通常只有一个类,方法很少。问题是调用这些方法可能很耗时——它们可能会挂起我的应用程序(调用这些方法时不会释放 GIL)。所以我的问题是:
为这些方法调用释放 GIL 的最简单方法是什么?
(我知道如果我使用 C 库,我可以用一些额外的 C 代码来包装它,但这里我使用 C++ 和类)
【问题讨论】:
【参考方案1】:不知道 SWIG 是什么,我还是会尝试回答 :)
使用类似的东西来释放/获取 GIL:
class GILReleaser
GILReleaser() : save(PyEval_SaveThread())
~GILReleaser()
PyEval_RestoreThread(save);
PyThreadState* save;
;
在您选择的代码块中,利用 RAII 来发布/获取 GIL:
GILReleaser releaser;
// ... Do stuff ...
【讨论】:
谢谢,你节省了我一些时间。【参考方案2】:真正的问题是 SWIG 没有很好地记录(我看到了使用更改日志进行搜索的提示;))。
好的,我发现我可以在 SWIG 中做内联函数并使用宏来释放/获取 GIL,它看起来像这样:
%inline %
void wrappedFunction(OriginalObject *o, <parameters>)
Py_BEGIN_ALLOW_THREADS
o->originalFunction(<parameters>);
Py_END_ALLOW_THREADS
%
此函数在原始 C++ 中不存在,但在 python 模块中可用。这(几乎)正是我想要的。 (我想要的是像 python 装饰器那样包装原始方法)
【讨论】:
使用 Henrik 的。这是正确的,但是是不好的 c++ 实践。此外,我在发布 GIL 后从 dict 中提取数据时发生崩溃,因此我通常在 GIL 发布和重新获取之间不使用 python.h 中的任何函数。【参考方案3】:您可以使用与 C 相同的 API 调用。没有区别。包含“python.h”并调用相应的函数。
另外,看看 SWIG 是否没有类型映射或其他东西来指示 GIL 不应该为特定功能保留。
【讨论】:
以上是关于在 C++ 代码中发布 Python GIL的主要内容,如果未能解决你的问题,请参考以下文章
如何在 boost::python 扩展模块中正确组合 C++ 和 Python 代码?
从 c++ 代码运行 python 脚本并在 c++ 中使用 pythons 输出