
Hi, I found an issue when accessing a shared_ptr C++ object in Python using Boost.Python. When I try to access an attribute of the shared_ptr object read from an C++ object, I get an error telling me that the attribute does not exist. When I use raw pointers instead of shared_ptr, then there is no issue. Also, when using raw pointers, accessing an item in a list of base class objects returns the object in as the derived most class. This is wanted. When I use shared_ptrs however, the derived most object is of the base class type. This is not wanted. I am sure the Boost.Python developers should be aware of these two issues by now. If so, is there any plans to fix this? If so, when? Below is a test showing this issue: *Raw pointers:* #include<memory> #include<vector> struct Vehicle{ virtual ~Vehicle(){} int testAttribute; }; struct Boat: public Vehicle { virtual ~Boat(){} int testBoatAttribute; }; struct Garage { std::vector<Vehicle*>& vehicleList() { return m_VehicleList; } std::vector<Vehicle*> m_VehicleList; }; #include <boost/python.hpp> #include <boost/python/suite/indexing/vector_indexing_suite.hpp> BOOST_PYTHON_MODULE(garage_ext) { using namespace boost::python; class_<Garage>("Garage") .def("vehicleList", &Garage::vehicleList, return_internal_reference<1>()); class_<Vehicle,Vehicle*,boost::noncopyable>("Vehicle", no_init) .def_readwrite("testAttribute", &Vehicle::testAttribute); class_<Boat,Boat*,bases<Vehicle>>("Boat") .def_readwrite("testBoatAttribute", &Boat::testBoatAttribute); implicitly_convertible<Boat*, Vehicle*>(); class_<std::vector<Vehicle*> >("stl_vector_Vehicle_ptr") .def(vector_indexing_suite<std::vector<Vehicle*>>()); } *Shared pointers:* #include<memory> #include<vector> #include <boost/shared_ptr.hpp> 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<boost::shared_ptr<Vehicle>>& vehicleList() { return m_VehicleList; } std::vector<boost::shared_ptr<Vehicle>> m_VehicleList; }; #include <boost/python.hpp> #include <boost/python/suite/indexing/vector_indexing_suite.hpp> BOOST_PYTHON_MODULE(garage_ext){ using namespace boost::python; class_<Garage>("Garage") .def("vehicleList", &Garage::vehicleList, return_internal_reference<1>()); class_<Vehicle,boost::shared_ptr<Vehicle>,boost::noncopyable>("Vehicle", no_init) .def_readwrite("testAttribute", &Vehicle::testAttribute); class_<Boat,boost::shared_ptr<Boat>, bases<Vehicle>>("Boat") .def_readwrite("testBoatAttribute", &Boat::testBoatAttribute); implicitly_convertible<boost::shared_ptr<Boat>, boost::shared_ptr<Vehicle>>(); class_<std::vector<boost::shared_ptr<Vehicle>>
("stl_vector_Vehicle_ptr")
.def(vector_indexing_suite<std::vector<boost::shared_ptr<Vehicle>>>()); } *Python test:* from garage_ext import * g = Garage() l = g.vehicleList() newboat = Boat() newboat.testAttribute = 3 newboat.testBoatAttribute = 5 l.append(newboat) print(type(l[0])) print(str(hasattr(l[0],"testAttribute"))) print(str(l[0].testAttribute)) b = l[0] print(type(b)) print(str(b.testBoatAttribute)) print("Done.") *Raw pointer result:* <class 'garage_ext.Boat'> True 3 <class 'garage_ext.Boat'> 5 Done. *Shared pointer result:* <class 'garage_ext.*Vehicle*'> *// Expected it to be Boat as with Raw pointers* Traceback (most recent call last): File "test_garage.py", line 9, in <module> print(str(hasattr(l[0],"testAttribute"))) *// Expected attribute to exist as with Raw pointers. Note: dir(l[0]) shows that it has the attribute. Accessing the attribute however throws an error.* Boost.Python.ArgumentError: Python argument types in None.None(Vehicle) did not match C++ signature: None(Vehicle {lvalue}) Kind Regards, Christoff