2015-02-22 2 views
0

У меня есть эти два класса:удалить указатель в станд :: вектор подвергается буста :: питона

typedef std::vector<Entity *> EntityPtrVector; 

class A 
{ 
private: 
    EntityPtrVector entity_vector; 

public: 
    void AddEntity(Entity *); 
    void RemoveEntity(std::string); 
}; 

class Entity 
{ 
private: 
    std::string name_; 

public: 
    Entity(); 
    Entity(std::string); 

    std::string GetName(void) const { return name_; } 
    void SetName(const std::string& name) { name_ = name; } 
}; 

Я разоблачить их повышения :: питона так:

BOOST_PYTHON_MODULE(my_lib) 
{ 
    using namespace boost::python; 

    class_<EntityPtrVector>("EntityPtrVector") 
     .def(vector_indexing_suite<EntityPtrVector>()); 

    class_<A>("A", init<std::string>()) 
     .def("AddEntity", &A::AddEntity) 
     .def("RemoveEntity", &A::RemoveEntity) 
    ; 

    class_<Entity>("Entity", init<std::string>()) 
     .add_property("name", &Entity::GetName, &Entity::SetName) 
    ; 
} 

Реализации из AddEntity и RemoveEntity являются:

void Game::AddEntity(Entity *E) 
{ 
    entity_vector.push_back(E); 
} 

void Game::RemoveEntity(std::string entity_name) 
{ 
    EntityPtrVector::iterator entity_ptr; 

    // Find the entity with the input name 
    for(entity_ptr = entity_vector.begin(); entity_ptr != entity_vector.end(); ++entity_ptr) 
    { 
     if((*entity_ptr)->GetName() == entity_name) 
     { 
      break; 
     } 
    } 
    // Remove the target entity 
    if(entity_ptr != entity_vector.end()) 
    { 
     delete *entity_ptr; 
     entity_vector.erase(entity_ptr); 
    } 
} 

Я уже проверил, что он работает под C++ witho ut подвергается воздействию python. В python части AddEntity и поиск целевого объекта успешны, но он сбой в команде delete *RemoveEntity (я проверяю их, добавляя инструкции журнала после каждой строки кодов). Это мой тестовый код в Python:

import my_lib 

test_a = my_lib.A("Test A") 
test_e = my_lib.Entity("Test Entity") 

test_a.AddEntity(test_e) 
test_a.RemoveEntity("Test Entity") 

Я думаю, может быть, я обличении std::vector<Entity *> Некорректно, но как я могу это исправить?

+0

Почему вы использовали фрагментированные фрагменты кода HTML/JavaScript для C++ и Python? –

+0

Можете ли вы сделать тест? Может быть, абстрагироваться от всего Python? И что сказал ваш отладчик? –

+0

В вашем коде нет доказательств, которые показывают, что ваши объекты были динамически распределены, поэтому вызов 'delete' приведет к неопределенному поведению для нединамически распределенных записей. – PaulMcKenzie

ответ

1
test_e = my_lib.Entity("Test Entity") 

создает объект Python, который является владельцем C++ Entity. Он управляет жизнью.

test_a.AddEntity(test_e) 

здесь мы передаем объект C++, обернутые test_e на С ++ объект обернут test_a. Объект C++ хранится в векторе A.

test_a.RemoveEntity("Test Entity") 

это удаляет Entity добавленный выше. Тем не менее, класс test_e * по-прежнему считает, что ему принадлежит Entity, так как нет способа сообщить, что вы передали право собственности. Но теперь он владеет недействительным указателем.

Авария происходит при удалении, потому что C++ не управляет этой памятью - python is. Он не использует кучу C++.

Вам необходимо иметь более прочную конструкцию для владения и управления жизненным циклом кода C++. Никогда delete что вы не сделали new, а код C++ в случае python никогда не new ed, что Entity.

+0

То есть, например, мне нужна функция-член, которая может new Entity и вернуть ее точку в C++, а затем дать этому правилу AddEntity право? – Ddavid

+0

@Ddavid вам нужно прекратить передачу объектов собственности через необработанные указатели C++. Используйте типизированные владельцы интеллектуальных указателей, если у вас есть право собственности. Затем создайте интерфейсы в Python. – Yakk

+0

Спасибо. Я новичок в boost :: python, поэтому я просто пытаюсь сделать что-то глупое ... – Ddavid