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& vehicleList() { return m_VehicleList; }
std::vector m_VehicleList;
};
#include
#include
BOOST_PYTHON_MODULE(garage_ext) {
using namespace boost::python;
class_<Garage>("Garage")
.def("vehicleList", &Garage::vehicleList,
return_internal_reference<1>());
class_("Vehicle", no_init)
.def_readwrite("testAttribute", &Vehicle::testAttribute);
class_("Boat")
.def_readwrite("testBoatAttribute", &Boat::testBoatAttribute);
implicitly_convertible();
class_ >("stl_vector_Vehicle_ptr")
.def(vector_indexing_suite>());
}
*Shared pointers:*
#include<memory>
#include<vector>
#include
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& vehicleList() { return
m_VehicleList; }
std::vector m_VehicleList;
};
#include
#include
BOOST_PYTHON_MODULE(garage_ext){
using namespace boost::python;
class_<Garage>("Garage")
.def("vehicleList", &Garage::vehicleList,
return_internal_reference<1>());
class_("Vehicle",
no_init)
.def_readwrite("testAttribute", &Vehicle::testAttribute);
class_("Boat")
.def_readwrite("testBoatAttribute", &Boat::testBoatAttribute);
implicitly_convertible();
class_
("stl_vector_Vehicle_ptr")
.def(vector_indexing_suite>());
}
*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:*
True
3
5
Done.
*Shared pointer result:*
*// 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