我正在使用pybind11在整数键和python对象之间实现映射。为了避免在对象之间存在循环引用(例如在自身中添加映射)时出现内存泄漏,通常会定义tp_traverse,但我看不到使用pybind进行此操作的任何方法。 这是一个示例:
#include <map>
#include <pybind11/pybind11.h>
namespace py = pybind11;
class MyMap {
public:
typedef std::map<int, py::object> MapType;
typedef typename MapType::iterator IteratorType;
virtual py::object get(int key) {
return _map[key];
}
virtual void put(int key, py::object value) {
_map[key] = value;
value.inc_ref();
}
void deleteItem(int key) {
IteratorType it = _map.find(key);
it->second.dec_ref();
_map.erase(it);
}
ssize_t size() const {
return _map.size();
}
protected:
MapType _map;
};
PYBIND11_MODULE(my_map, m) {
py::class_<MyMap>(m, "MyMap")
.def(py::init<>())
.def("size", &MyMap::size)
.def("delete_item", &MyMap::deleteItem)
.def("get", &MyMap::get)
.def("put", &MyMap::put);
}
这是我尝试做的简约版本。
我用python编写了一个执行以下操作的测试:
def test_traverse(self):
_map = MyMap()
self.assertTrue(gc.is_tracked(_map))
_map.put(1, 'test')
_map.put(2048, 'foo')
_map.put(4096, 'bar')
self.assertEqual(len(gc.get_referents(_map.store)), 3)
但是_map对象没有引用对象。以我的理解,我应该做的是使MyMap
的tp_traverse行为正确,但是我看不到这样做的方法。我尝试将keep_alive
参数添加到def("put"
调用中,但这似乎没有完成。我想念什么吗?还有其他方法可以使用pybind11完成吗?