Hi,

I'm struggling with the following issue in a boost.python implementation:
I have a list of std::shared_ptr in C++, I am accessing this list from Python.
 - When I access an element in the list, the elements does not have any attributes apparently. I get an error trying to access an attribute, hasattr returns false on the attribute, but dir informs me that it exist.
 - When I change the C++ implementation from shared_ptr to raw ptr's everything works as expected.
 - I want to use shared_ptrs for what I feel: obvious reasons.

Below is the C++ code and the Python code.

###################
### garage_ext.cpp ###
###################

#include<memory>
#include<vector>
namespace boost { template<class T> T* get_pointer(std::shared_ptr<T>& p){ return p.get(); }}

struct Vehicle{ 
   virtual ~Vehicle(){}
  friend bool operator==(const Vehicle& lhs, const Vehicle& rhs) { return true; }
  int testAttribute;
};
struct Boat: public Vehicle { 
   virtual ~Boat(){}
  friend bool operator==(const Boat& lhs, const Boat& rhs) { return true; } 
  int testBoatAttribute;
};
struct Garage {
    friend bool operator==(const Garage& lhs, const Garage& rhs) { return true; }
    std::vector<std::shared_ptr<Vehicle>>& vehicleList() { return m_VehicleList; }
    std::vector<std::shared_ptr<Boat>>& boatList() { return m_BoatList; }
    std::vector<std::shared_ptr<Vehicle>> m_VehicleList;
    std::vector<std::shared_ptr<Boat>> m_BoatList;
};
    
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
class BoatWrap : public Boat, public boost::python::wrapper<Boat> {
public:
    static std::shared_ptr<Boat> cast(std::shared_ptr<Vehicle> const& v) { return std::dynamic_pointer_cast<Boat>(v); }  
};
BOOST_PYTHON_MODULE(garage_ext)
{
    using namespace boost::python;
    class_<Garage>("Garage")
        .def("vehicleList", &Garage::vehicleList, return_internal_reference<1>())
        .def("boatList", &Garage::boatList, return_internal_reference<1>())
    ;
    class_<Vehicle, std::shared_ptr<Vehicle>,boost::noncopyable>("Vehicle", no_init)
.def_readwrite("testAttribute", &Vehicle::testAttribute)
    ;
    class_<BoatWrap,std::shared_ptr<Boat>,bases<Vehicle>>("Boat")
        .def("cast", &BoatWrap::cast)
.staticmethod("cast")
.def_readwrite("testBoatAttribute", &Boat::testBoatAttribute)
    ;
   
    implicitly_convertible<std::shared_ptr<Boat>,std::shared_ptr<Vehicle>>();
    class_<std::vector<std::shared_ptr<Vehicle>> >("stl_vector_Vehicle_ptr")
       .def(vector_indexing_suite<std::vector<std::shared_ptr<Vehicle>> >());
    class_<std::vector<std::shared_ptr<Boat>> >("stl_vector_Boat_ptr")
       .def(vector_indexing_suite<std::vector<std::shared_ptr<Boat>> >());
}



#####################
### Python test code ###
#####################
g = Garage()
l = g.boatList()
newboat = Boat()
l.append(newboat)
boatFromList = l[0]
print(type(boatFromList))
print(str(hasattr(newboat,"testBoatAttribute")))
dir(boatFromList)
# The following line throws the error.
print(str(hasattr(boatFromList,"testBoatAttribute")))


I created a cast method for boat.
If I cast l[0] to Boat using:
boatFromList = Boat.cast(l[0])
print(str(hasattr(boatFromList,"testBoatAttribute")))
works.

This is all very strange to me. It feels very buggy. Could someone please help me clarify the reason for this behavious?

Regards,
Christoff