Hi, I am having an issue with Boost.Python with a very simple use case.
I am returning a reference to an object, and it seems that my python object looses its C++ object's reference at a stage for some reason. Please see my *example* below reproducing this issue. *C++ Code:* #include <iostream> #include <vector> #include <string> #include <cmath> #include <boost/python.hpp> #include <boost/python/suite/indexing/vector_indexing_suite.hpp> class Car { public: Car(std::string name) : m_name(name) {} bool operator==(const Car &other) const { return m_name == other.m_name; } std::string GetName() { return m_name; } private: std::string m_name; }; class Factory { public: Factory(std::string name) : m_name(name) {} bool operator==(const Factory &other) const { return m_name == other.m_name && m_car_list == other.m_car_list; } Car& create_car(std::string name) { m_car_list.emplace_back(Car(name)); return m_car_list.back(); } std::string GetName() { return m_name; } std::vector<Car>& GetCarList() { return m_car_list;} private: std::string m_name; std::vector<Car> m_car_list; }; class Manufacturer { public: Manufacturer(std::string name) : m_name(name) {} bool operator==(const Manufacturer &other) const { return m_name == other.m_name && m_factory_list == other.m_factory_list; } Factory& create_factory(std::string name) { m_factory_list.emplace_back(Factory(name)); return m_factory_list.back(); } std::string GetName() { return m_name; } std::vector<Factory>& GetFactoryList() { return m_factory_list;} private: std::string m_name; std::vector<Factory> m_factory_list; }; BOOST_PYTHON_MODULE(carManufacturer) { using namespace boost::python; class_<Manufacturer>("Manufacturer", init<std::string>()) .add_property("factory_list", make_function(&Manufacturer::GetFactoryList, return_internal_reference<1>())) .add_property("name", &Manufacturer::GetName) .def("create_factory", &Manufacturer::create_factory, return_internal_reference<>()); class_<Factory>("Factory", init<std::string>()) .add_property("car_list", make_function(&Factory::GetCarList, return_internal_reference<1>())) .add_property("name", &Factory::GetName) .def("create_car", &Factory::create_car, return_internal_reference<>()); class_<Car>("Car", init<std::string>()) .add_property("name", &Car::GetName); class_<std::vector<Factory> >("FactoryList") .def(vector_indexing_suite<std::vector<Factory> >()); class_<std::vector<Car> >("Car") .def(vector_indexing_suite<std::vector<Car> >()); } *Python Code:* import sys sys.path[:0] = [r"bin\Release"] from carManufacturer import * vw = Manufacturer("VW") vw_bra_factory = vw.create_factory("Brazil Factory") beetle = vw_bra_factory.create_car("Beetle69") if vw_bra_factory is vw.factory_list[0]: print("equal.") else: print("NOT EQUAL") print("## I expected them to be the same reference..?") print("vw_bra_factory Car List size : " + str(len(vw_bra_factory.car_list))) print("Actual Car List size : " + str(len(vw.factory_list[0].car_list))) print("## This still works. Maybe the python objects differ, but refer to the same C++ object. I can live with that.") vw_sa_factory = vw.create_factory("South Africa Factory") print("vw_bra_factory Car List size : " + str(len(vw_bra_factory.car_list))) print("Actual Car List size : " + str(len(vw.factory_list[0].car_list))) print("## .. what? why? brazil py object has no cars now? I don't get it. I can't have any of that.") print("## What will happen if I create another car in the brazil factory?") combi = vw_bra_factory.create_car("Hippie van") print("vw_bra_factory Car List size : " + str(len(vw_bra_factory.car_list))) print("Actual Car List size : " + str(len(vw.factory_list[0].car_list))) print("## And another.") citi_golf = vw_bra_factory.create_car("Citi golf") print("vw_bra_factory Car List size : " + str(len(vw_bra_factory.car_list))) print("Actual Car List size : " + str(len(vw.factory_list[0].car_list))) print("## 'vw_bra_factory' must have lost its C++ reference it had to 'vw.factory_list[0]' when I created a new factory. Why?") *Python Output:* NOT EQUAL *## I expected them to be the same reference..?* vw_bra_factory Car List size : 1 Actual Car List size : 1 *## This still works. Maybe the python objects differ, but refer to the same C++ object. I can live with that.* vw_bra_factory Car List size : 0 Actual Car List size : 1 *## .. what? why? brazil py object has no cars now? I don't get it. I can't have any of that.* *## What will happen if I create another car in the brazil factory?* vw_bra_factory Car List size : 1 Actual Car List size : 1 *## And another.* vw_bra_factory Car List size : 2 Actual Car List size : 1 *## 'vw_bra_factory' must have lost its C++ reference it had to 'vw.factory_list[0]' when I created a new factory. Why?* This is just an example made to reproduce my real work's problem in a presentable way. In my real work, python crashes after I create a second "factory" and try to add a "car" to the first "factory". The crash occurs in C++ "create_car" method whan trying to access the "factory"'s "car" list. Does anyone have insight as to what the problem is? Any useful input will be greatly appreciated. Greetings, Christoff
_______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org https://mail.python.org/mailman/listinfo/cplusplus-sig