2015-05-28 70 views
0

我遇到了一個Boost.Python問題,它帶有一個非常簡單的用例。Python中的Boost.Python C++對象引用:意外行爲

我返回一個對象的引用,似乎我的python對象由於某種原因在某個階段失去了它的C++對象的引用。

請參閱下面的示例重現此問題。

C++代碼:

#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代碼:

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的輸出:

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? 

這僅僅是做重現一個像樣的路我的實際工作中的問題的例子。在我的真實工作中,在創建第二個「工廠」並嘗試向第一個「工廠」添加「汽車」後,python崩潰 。 崩潰發生在嘗試訪問「工廠」的「汽車」列表的C++「create_car」方法中。

有沒有人知道問題是什麼?任何有用的輸入將不勝感激。

回答

0

感謝某人爲圖中的郵件列表上的問題出來了:

它工作時,我保留矢量大小,以如32.

它也可以工作,如果我分配存儲在堆向量中的對象。