如何使用 pybind11 将 python 函数保存到静态 C++ 容器?
How can I save a python function to a static c++ container using pybind11?
本质上,在 C++ 方面,我有一个包含特定类型函数的容器。现在我想将此容器公开给 python,用户可以提供自己的 python 功能。
最简单的示例如下所示:
#include "pybind/common/Common.h"
using CppFunc = std::function< int (int) >;
PYBIND11_MODULE( test, m )
{
m.def("addFunc", [](const pybind11::function& f){
static std::vector<CppFunc> vec{};
vec.push_back(f.cast<CppFunc>());
});
}
然后在python我想做这样的事情。
import test
def myFunc(number):
return number+1
test.addFunc(myFunc)
有趣的是,这工作正常。但是,如果我 运行 带有 "python script.py" 的脚本,它 运行 就会通过,然后永远不会终止。在交互式控制台中,相同的代码可以正常工作,直到您尝试关闭控制台:进程卡住。
如何安全地将此 python 函数存储在 C++ 容器中?
static std::vector<CppFunc> vec{}
存储对 python 对象(用户函数)的引用,这些对象(用户函数)由于静态存储而永远不会被释放,因此解释器无法终止。
为确保解释器终止,您可以在模块终止时调用清理函数:
#include "pybind11/pybind11.h"
#include "pybind11/functional.h"
namespace py = pybind11;
using CppFunc = std::function< int (int) >;
PYBIND11_MODULE( test , m )
{
static std::vector<CppFunc> vec{};
m.def("addFunc", [](CppFunc f){
vec.push_back(std::move(f));
});
m.add_object("_cleanup", py::capsule([]{ vec.clear(); }));
}
有关详细信息,请参阅文档:https://pybind11.readthedocs.io/en/stable/advanced/misc.html#module-destructors
本质上,在 C++ 方面,我有一个包含特定类型函数的容器。现在我想将此容器公开给 python,用户可以提供自己的 python 功能。
最简单的示例如下所示:
#include "pybind/common/Common.h"
using CppFunc = std::function< int (int) >;
PYBIND11_MODULE( test, m )
{
m.def("addFunc", [](const pybind11::function& f){
static std::vector<CppFunc> vec{};
vec.push_back(f.cast<CppFunc>());
});
}
然后在python我想做这样的事情。
import test
def myFunc(number):
return number+1
test.addFunc(myFunc)
有趣的是,这工作正常。但是,如果我 运行 带有 "python script.py" 的脚本,它 运行 就会通过,然后永远不会终止。在交互式控制台中,相同的代码可以正常工作,直到您尝试关闭控制台:进程卡住。
如何安全地将此 python 函数存储在 C++ 容器中?
static std::vector<CppFunc> vec{}
存储对 python 对象(用户函数)的引用,这些对象(用户函数)由于静态存储而永远不会被释放,因此解释器无法终止。
为确保解释器终止,您可以在模块终止时调用清理函数:
#include "pybind11/pybind11.h"
#include "pybind11/functional.h"
namespace py = pybind11;
using CppFunc = std::function< int (int) >;
PYBIND11_MODULE( test , m )
{
static std::vector<CppFunc> vec{};
m.def("addFunc", [](CppFunc f){
vec.push_back(std::move(f));
});
m.add_object("_cleanup", py::capsule([]{ vec.clear(); }));
}
有关详细信息,请参阅文档:https://pybind11.readthedocs.io/en/stable/advanced/misc.html#module-destructors