Cómo configurar una función de Python como callback para C++ utilizando pybind11?
typedef bool (*ftype_callback)(ClientInterface* client, const Member* member, int member_num);
struct Member {
char x[64];
int y;
};
class ClientInterface {
public:
virtual int calc() = 0;
virtual bool join() = 0;
virtual bool set_callback(ftype_callback on_member_join) = 0;
};
Es un SDK desde el cual puedo llamar al cliente desde una biblioteca dinámica en los códigos de C++.
bool cb(ClientInterface* client, const Member* member, int member_num) {
// hacer algo
}
cli->set_callback(cb);
cli->join();
Quiero portarlo a enlaces en Python usando pybind11. ¿Cómo puedo establecer el callback en Python?
He consultado la documentación y he intentado:
PYBIND11_MODULE(xxx, m) {
m.def("set_callback", [](xxx& self, py::function cb) {
self.set_callback(cb);
});
}
El código simplemente no compila.
Mi pregunta es, ¿cómo puedo convertir py::function
a ftype_callback
o hay otra manera de hacerlo?
davy.ai
Para convertir
py::function
aftype_callback
en pybind11, puedes usarpy::cpp_function::make()
para envolver la función de callback de Python y luego convertirla al puntero de función esperado. Aquí tienes un ejemplo de implementación de la funciónset_callback
:“`c++
#include
#include “your_sdk_header.h” // reemplazar con el encabezado real del SDK
#include
namespace py = pybind11;
PYBIND11_MODULE(example, m) {(m, “ClientInterface”)(
py::class_
.def(“calc”, &ClientInterface::calc)
.def(“join”, &ClientInterface::join)
.def(“set_callback”, [](ClientInterface &self, py::function cb) {
ftype_callback cb_c = reinterpret_cast
py::cpp_function(cb).cast<void*>());
self.set_callback(cb_c);
});
}
“`
py::cpp_function(cb)
crea un objeto de función con tipo borrado que se puede convertir avoid*
, el cual se convierte al tipo de puntero de función esperadoftype_callback
utilizandoreinterpret_cast
. Ten en cuenta que esto solo es seguro si la función de callback de Python tiene una firma compatible, es decir, toma parámetrosClientInterface*
,const Member*
eint
y devuelve unbool
.Con esta implementación, puedes pasar una función de Python como argumento de callback:
“`python
import example
def cb(cliente, miembro, num_miembro):
# hacer algo
return True
cli = example.ClientInterface()
cli.set_callback(cb)
cli.join()
“`</void*>