Обертывание выделенного экземпляра C ++ с pybind11 - PullRequest
2 голосов
/ 08 октября 2019

При встраивании python в C ++ через PyBind11 я застрял в следующей проблеме. Предположим, я сгенерировал экземпляр shared_ptr объекта через C ++ и затем хочу передать этот указатель на pybind11, чтобы сгенерировать для него «теневую» привязку python.

Вот моя первоначальная, нерабочая попытка:

#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");
}

Итак, мои вопросы:

  • Итак, как я могу создать «теневой класс» для C ++ shared_ptr?
  • Как я могу «назначить» C ++ shared_ptrк переменной Python?

1 Ответ

1 голос
/ 24 октября 2019

Если вы проверите получившийся объект py :: из приведения (например, приведя его к bool), вы увидите, что вызов не удался. Причина в том, что питон не знает класс «Pet» (ни shared_ptr). Вы можете использовать код, описанный выше, и создать из него модуль обычным способом, а затем импортировать его в основную программу. Или используйте функцию EMBEDDED_MODULE, которая ближе к тому, к чему вы стремитесь.

Настройка вашего примера:

#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");
}
...