我有这两个类:
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暴露它们:
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 ++下工作而不暴露给python。在python中,AddEntity
的部分和查找目标实体是成功的,但它在delete *
的{{1}}指令崩溃(我通过在每行代码后添加日志指令来检查这些) 。这是我在python中的测试代码:
RemoveEntity
我想也许我会错误地揭露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")
,但我怎么能纠正这个?
答案 0 :(得分:1)
test_e = my_lib.Entity("Test Entity")
创建一个拥有C ++ Entity
的Python对象。它管理着整个生命周期。
test_a.AddEntity(test_e)
这里我们将test_e
包装的C ++对象传递给test_a
包装的C ++对象。 C ++对象存储在A
。
test_a.RemoveEntity("Test Entity")
这会删除您在上面添加的Entity
。但是,test_e
类*仍然认为它拥有Entity
,因为没有办法告诉您通过了所有权。但现在它拥有一个无效的指针。
崩溃发生在删除,因为C ++没有管理那个内存 - python是。它不使用C ++堆。
您需要在C ++代码中拥有更完善的所有权和生命周期管理设计。永远不会delete
你没有new
,而python案例中的C ++代码永远不会new
编辑Entity
。