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