我无法将类方法的输入(输入:单独类的特定实例)返回给Python。绑定编译后,我可以在 Python 中使用生成的模块。然而,类方法应该返回与其承认的相同的实例(经过一些处理后)。
Obstacle
类用作输入。 ObstacleProcess
类有一个处理输入(__call__
的实例)的方法(Python:operator_py
/ C++:Obstacle
)。以下 Python 代码显示返回 Obstacle
的不同实例:
import example
obstacle_1 = example.Obstacle()
obstacle_2 = example.Obstacle()
obstacles = [obstacle_1, obstacle_2]
print(obstacles)
params = example.Params()
obstacle_process = example.ObstacleProcess(params)
obstacles = obstacle_process(obstacles)
print(obstacles)
第一个打印返回:
[<example.Obstacle object at 0x7fb65271e1b0>, <example.Obstacle at 0x7fb652735070>]
,而第二个打印返回:[<example.Obstacle at 0x7fb652734670>, <example.Obstacle object at 0x7fb652735230>]
。
这不是所需的输出,因为
obstacle_1
最初位于 0x7fb65271e1b0
,在 operator()
/__call__
调用后,它位于 0x7fb652734670
。我希望 obstacle_1
保留其初始地址 0x7fb65271e1b0
,即使在另一个类 (ObstacleProcess
) 处理完 obstacle_1
后也是如此。
以下代码为与pybind11绑定的源码:
// pybind11 binding
py::class_<Obstacle, std::shared_ptr<Obstacle>>(m, "Obstacle")
.def(py::init<>());
py::class_<ObstacleProcess>(m, "ObstacleProcess")
.def(py::init<
const Params&>()
)
.def("__call__", &ObstacleProcess::operator_py<Params>, py::return_value_policy::reference);
下一个块展示了
operator_py
是如何在源代码中实现的:
template <Params>
std::vector<Obstacle>& operator_py(
std::vector<Obstacle>& obstacles,
const Params ¶meters
)
{
...
return obstacles
}
我尝试过有或没有
std::shared_ptr<Obstacle>
。当前的实现给出了与根本不使用shared_ptr
相同的结果,因此我实现shared_ptr
的方式有问题。我尝试过使用PYBIND11_MAKE_OPAQUE(std::shared_ptr<std::vector<Obstacle>>);
,但我的实现并没有改变结果。
我没有尝试过使用
pybind11 — smart_holder branch
,也许这个分支必须用于这种情况?
感谢 @DanMašek 和 @n.m.willseey'allonReddit 的评论,我们发现对
operator_py()
进行这些更改可以修复问题中的问题:
template <class Params>
std::vector<std::shared_ptr<Obstacle>> operator_py(
std::vector<std::shared_ptr<Obstacle>> &obstacle_ptrs,
const Params ¶ms
)
{
std::vector<Tracked_Obstacle> obstacles;
for (const auto& obstacle_ptr_0 : obstacle_ptrs)
{
if (obstacle_ptr_0)
{
obstacles.push_back(*obstacle_ptr_0);
}
else
{
std::cout<<"nlptr"<<std::endl;
}
}
for (const auto& obstacle_ptr : obstacle_ptrs)
{
Tracked_Obstacle& obstacle = *obstacle_ptr;
// do processing ...
};
return obstacle_ptrs;
通过此实现,获得了所需的输出:
import example
obstacle_1 = example.Obstacle()
obstacle_2 = example.Obstacle()
obstacles = [obstacle_1, obstacle_2]
print(obstacles)
params = example.Params()
obstacle_process = example.ObstacleProcess(params)
obstacles = obstacle_process(obstacles)
print(obstacles)
# output:
[<example.Obstacle object at 0x7f709bdc2430>, <example.Obstacle object at 0x7f709b12a830>]
[<example.Obstacle object at 0x7f709bdc2430>, <example.Obstacle object at 0x7f709b12a830>]