如何将共享指针列表传递给 pybind11 中的 C++ 对象
How to pass list of shared pointers to c++ object in pybind11
我正在构建一个 ml 项目,它将使用 tensorflow、由 c++ 库控制的游戏规则集和 python 个玩家。
我决定使用 pybind 作为游戏规则引擎和玩家控制层之间的转换层。
这是我尝试用 pybind 包装的 classes:
class Player
{
public:
Player() = default;
virtual PlayerId getId() const = 0;
virtual void playTurn(Turn&) = 0;
virtual void takeHint(std::list<CardId>, Color) = 0;
virtual void takeHint(std::list<CardId>, Value) = 0;
virtual ~Player() = default;
};
using Players = std::list<std::shared_ptr<Player>>;
class Game
{
(...)
public:
Game(const Game&) = delete;
Game(Game&&) = delete;
Game(const Players& players, const Cards&);
void turn();
int getScore() const;
};
这是我的包装方式:
PYBIND11_MODULE(hanabi_py, m)
{
m.doc() = "hanabi-cpp wrapper for python";
py::class_<Game>(m, "Game")
.def(py::init<const Players&, const Cards&>())
.def("turn", &Game::turn)
.def("getScore", &Game::getScore);
py::class_<Player, std::shared_ptr<Player>, PyPlayer>(m, "Player")
.def(py::init<>())
.def("getId", &Player::getId, "Get id")
.def("playTurn", &Player::playTurn, "Play turn", py::arg("turn"))
.def("takeHint",
py::overload_cast<std::list<CardId>, Color>(&Player::takeHint),
"take color hint")
.def("takeHint",
py::overload_cast<std::list<CardId>, Value>(&Player::takeHint),
"take value hint");
(...)
}
完整代码位于:https://github.com/morynicz/hanabi-cpp
尝试创建游戏时:
import hanabi_py as h
class PyPlayer(h.Player):
def __init__(self, id):
h.Player.__init__(self)
self.id = id
def getId(self):
return self.id
def playTurn(self,turn):
pass
def takeHint(self, ids, arg):
pass
def attempt():
p = PyPlayer(1)
c = h.Card
c.id = 0
c.color = h.Color.Red
c.value = h.Value.One
g = h.Game([p],[c])
我得到:
TypeError: init(): incompatible constructor arguments. The following argument types are supported:
1. hanabi_py.Game(arg0: List[Player], arg1: List[Card])
问题
如何在将 python class 派生自 C++ class 的 python 对象包装到 shared_ptr 中,然后再将其放入列表中?
我知道我可以尝试添加一些函数来用 shared_ptr 包装 python 对象,但请记住,已经有 shared_ptr 持有者在使用这似乎是很糟糕的主意。
编辑:
看来问题不在shared_ptr,而在列表。由于某种原因,它没有得到妥善解决。我尝试为玩家制作一个不透明的class,但它不起作用
TypeError: init(): incompatible constructor arguments. The following argument types are supported:
1. hanabi_py.Game(players: std::__cxx11::list, std::allocator > >, cards: List[Card])
所以目前的问题是:
如何将 python 对象列表作为 std::list> 从 python 传递给 C++ 对象?
这一行:
c = h.Card
使 c
成为 Card
类型。你需要在py::class_<Card>(m, "Card")
的构造中添加一个构造函数.def(py::init<>())
,然后做c = h.Card()
.
我正在构建一个 ml 项目,它将使用 tensorflow、由 c++ 库控制的游戏规则集和 python 个玩家。
我决定使用 pybind 作为游戏规则引擎和玩家控制层之间的转换层。
这是我尝试用 pybind 包装的 classes:
class Player
{
public:
Player() = default;
virtual PlayerId getId() const = 0;
virtual void playTurn(Turn&) = 0;
virtual void takeHint(std::list<CardId>, Color) = 0;
virtual void takeHint(std::list<CardId>, Value) = 0;
virtual ~Player() = default;
};
using Players = std::list<std::shared_ptr<Player>>;
class Game
{
(...)
public:
Game(const Game&) = delete;
Game(Game&&) = delete;
Game(const Players& players, const Cards&);
void turn();
int getScore() const;
};
这是我的包装方式:
PYBIND11_MODULE(hanabi_py, m)
{
m.doc() = "hanabi-cpp wrapper for python";
py::class_<Game>(m, "Game")
.def(py::init<const Players&, const Cards&>())
.def("turn", &Game::turn)
.def("getScore", &Game::getScore);
py::class_<Player, std::shared_ptr<Player>, PyPlayer>(m, "Player")
.def(py::init<>())
.def("getId", &Player::getId, "Get id")
.def("playTurn", &Player::playTurn, "Play turn", py::arg("turn"))
.def("takeHint",
py::overload_cast<std::list<CardId>, Color>(&Player::takeHint),
"take color hint")
.def("takeHint",
py::overload_cast<std::list<CardId>, Value>(&Player::takeHint),
"take value hint");
(...)
}
完整代码位于:https://github.com/morynicz/hanabi-cpp
尝试创建游戏时:
import hanabi_py as h
class PyPlayer(h.Player):
def __init__(self, id):
h.Player.__init__(self)
self.id = id
def getId(self):
return self.id
def playTurn(self,turn):
pass
def takeHint(self, ids, arg):
pass
def attempt():
p = PyPlayer(1)
c = h.Card
c.id = 0
c.color = h.Color.Red
c.value = h.Value.One
g = h.Game([p],[c])
我得到:
TypeError: init(): incompatible constructor arguments. The following argument types are supported: 1. hanabi_py.Game(arg0: List[Player], arg1: List[Card])
问题
如何在将 python class 派生自 C++ class 的 python 对象包装到 shared_ptr 中,然后再将其放入列表中?
我知道我可以尝试添加一些函数来用 shared_ptr 包装 python 对象,但请记住,已经有 shared_ptr 持有者在使用这似乎是很糟糕的主意。
编辑: 看来问题不在shared_ptr,而在列表。由于某种原因,它没有得到妥善解决。我尝试为玩家制作一个不透明的class,但它不起作用
TypeError: init(): incompatible constructor arguments. The following argument types are supported: 1. hanabi_py.Game(players: std::__cxx11::list, std::allocator > >, cards: List[Card])
所以目前的问题是: 如何将 python 对象列表作为 std::list> 从 python 传递给 C++ 对象?
这一行:
c = h.Card
使 c
成为 Card
类型。你需要在py::class_<Card>(m, "Card")
的构造中添加一个构造函数.def(py::init<>())
,然后做c = h.Card()
.