When embedding python in C++ through PyBind11, I got stuck on the following issue. Consider I generate a shared_ptr instance of an object through C++ and I then want to handover this pointer to pybind11 to generate a "shadow" python binding for it.
Here is my initial, non-working attempt:
#include <stdio.h>
#include <pybind11/pybind11.h>
#include <pybind11/embed.h>
using namespace std;
namespace py = pybind11;
class Pet
{
public:
Pet() {}
void bark(void) { printf("wow!\n"); }
};
PYBIND11_PLUGIN(Pets) {
py::module m("Pets", "Say hello to our pets");
py::class_<Pet, shared_ptr<Pet>>(m, "Pet")
.def("bark", &Pet::bark)
;
return m.ptr();
}
int main(int argc, char *argv[])
{
py::scoped_interpreter guard{};
shared_ptr<Pet> pet = make_shared<Pet>();
// How do Ι "assign" Pet.pet to the C++ pet? This compiles,
// but throws a run time exception:
py::globals()["pet"] = py::cast(pet);
py::exec("pet.bark()\n");
}
So my questions are:
If you check the resulting py::object from the cast (e.g. by casting it to bool), you will see that the call failed. The reason is that the python does not know the class "Pet" (nor shared_ptr). You can either use the code as above and create a module from it the usual way, then import that in a main program. Or, use the EMBEDDED_MODULE feature, which is closer to what you appear to be going for.
Adjusting your example:
#include <stdio.h>
#include <pybind11/pybind11.h>
#include <pybind11/embed.h>
using namespace std;
namespace py = pybind11;
class Pet
{
public:
Pet() {}
void bark(void) { printf("wow!\n"); }
};
PYBIND11_EMBEDDED_MODULE(Pets, m) {
py::class_<Pet, shared_ptr<Pet>>(m, "Pet")
.def("bark", &Pet::bark)
;
}
int main(int argc, char *argv[])
{
py::scoped_interpreter guard{};
shared_ptr<Pet> pet = make_shared<Pet>();
auto pets_mod = py::module::import("Pets");
py::globals()["pet"] = py::cast(pet);
py::exec("pet.bark()\n");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With