Boost logo

Boost Users :

Subject: [Boost-users] Boost.Python C++ pointer object to python: Attribute does not exist.
From: Christoff Kok (christoff.kok_at_[hidden])
Date: 2014-11-07 03:25:50


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



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net