Garmaine Staff asked 1 year ago

I am trying to handle pointers within friend classes in PyBind11. The problem is that I am not able to retrieve the pointed values of a friend class object in Python. The toy example works, but the values are totally different than what they should be. I thought initially that it would be because of the friend class, but according to my readings and understanding I don't think it is. I also wasn't able to find anything in the documentation

example.cpp

#include <pybind11/pybind11.h>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <list>
#include <vector>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>

namespace py = pybind11;

class Owner;
class Pet {

    friend Owner;

    public:
      std::string name;
      int a;
      Pet(const std::string name_, int b){
          name = name_;
          a = b;
      }

      Pet(const std::string name_){
        name = name_;
        a = 23;
      }

    int repr(){
      return a;
    }
};

class Owner {

      public:
        int owner_id;
        Pet* their_pet;

      Owner(int owner_id_, Pet *their_pet_){
        owner_id = owner_id_;
        their_pet = their_pet_;
      }
};


int retrieve(py::handle the_owner){
  Owner an_owner = the_owner.cast<Owner>();
  Pet* the_retrieved_pet = an_owner.their_pet;
  int the_age = the_retrieved_pet->repr();
  std::cout << the_age << std::endl;
  return the_age;
}

py::object create_neat(){

  Pet dog = Pet("rufus", 2);
  Pet* ptr_dog = &dog;
  Owner owner_1 = Owner(1, ptr_dog);
  py::object py_owner = py::cast(owner_1);
  return py_owner;

}

PYBIND11_MODULE(example, m){
  py::class_<Pet>(m, "Pet")
      .def(py::init<const std::string>())
      .def("repr", &Pet::repr);

  py::class_<Owner>(m, "Owner");

  m.def("retrieve", &retrieve, "return the python object to its class");

  m.def("create_neat", &create_neat, "return the python object to its class");
}

Compilable with:

g++ -O3 -Wall -fopenmp -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` example.cpp -o example.so

In Python

import example

a = example.create_neat()
b = example.retrieve(a)

b should be 2, and instead, it is a totally different value. Any help would be more than appreciated.