[英]Application crashes with objects created in loop using Luabind in C++
我正在尝试将Lua与我的游戏引擎原型一起使用,但遇到了奇怪的错误。
我的目标是与Lua循环创建X对象并渲染它们。
sprite = Sprite("icon.jpg", 300, 300, 0)
sprite2 = Sprite("icon.jpg", 100, 100, 0)
b1 = BoxObject(sprite)
b2 = BoxObject(sprite2)
sprite3 = Sprite("circle.png", 200, 100, 0)
sprite4 = Sprite("circle.png", 300, 100, 0)
b3 = CircleObject(sprite3)
b4 = CircleObject(sprite4)
n = Node()
n:AddChild(b1)
n:AddChild(b2)
n:AddChild(b3)
n:AddChild(b4)
for i = 0, 10, 1 do
x = math.random(700)
y = math.random(500)
n:AddChild(BoxObject(Sprite("icon.jpg", x, y, 0)))
end
for i = 0, 10, 1 do
x = math.random(700)
y = math.random(500)
local s = Sprite("circle.png", x, y, 0)
local o = CircleObject(s)
n:AddChild(BoxObject)
end
如果我这样做,代码可以正常工作,但是游戏会在随机时间内从几秒钟崩溃。 如果仅将此代码用于循环创建的对象,而不是手动创建的对象,则游戏会立即崩溃。
但是,如果我用C ++编写等效于Lua的代码,则它可以正常运行。
for(int i = 0; i < 20; i++){
float x = rand() % 700;
float y = rand() % 500;
n->AddChild(new BoxObject(new Sprite("icon.jpg", x, y)));
}
for(int i = 0; i < 20; i++){
float x = rand() % 700;
float y = rand() % 500;
n->AddChild(new CircleObject(new Sprite("circle.png", x, y)));
}
这是我的Lua绑定
static void Lua(lua_State *lua){
luabind::module(lua)
[
luabind::class_<Node>("Node")
.def(luabind::constructor<>())
.def(luabind::constructor<float, float, float>())
.def("Render", &Node::Render)
.def("Move", &Node::Move)
.def("Rotate", &Node::Rotate)
.def("AddChild", &Node::AddChild)
.def("RotateAroundPoint", &Node::RotateAroundPoint)
];
}
除AddChild之外,每个方法均接受并返回void
virtual void AddChild(Node *child);
Sprite和Box aand Circle对象是从Node类继承的。
有谁知道会导致这种奇怪错误的原因吗? 我很乐意提供任何帮助。
您有严重的所有权问题。
在C / C ++中,一段代码“拥有”一个指针或其他资源(如果该代码或对象承担销毁它的责任)。 它保持它活着,而它需要它,它可以确保当使用完被摧毁。
保持对谁拥有什么的理解,这对于任何甚至非常复杂的C或C ++程序都至关重要。
当Luabind 从Lua创建C ++对象时 ,Lua脚本将拥有该对象。 这意味着Lua的垃圾收集器将决定何时删除它。
所以这:
local s = Sprite("circle.png", x, y, 0)
将创建一个生命周期受Lua状态控制的Sprite
对象。 当Lua状态不再具有对其的任何活动引用时,则Lua状态将可以自由删除它。
我不知道您的代码如何工作,但是这一行:
local o = CircleObject(s)
建议CircleObject
的构造函数应该声明对其所给定对象的所有权(因此CircleObject
决定何时删除它)。 如果是这样,那么在将此构造函数与Luabind绑定时,您需要实际声明。
如果不应该使用CircleObject
的构造方法来拥有所有权,那么……坦率地说,您的设计CircleObject
怀疑; 长期存储您不拥有的指针只是在乞求弄糟。 但是,如果确实要存储别人拥有的指针,则您需要使用Lua机制来确保Sprite
只要CircleObject
保持活动CircleObject
。
类似地, Node::AddChild
函数看起来像在声明所给定节点的所有权。 可以这样进行:
.def("AddChild", &Node::AddChild, adopt(_1))
_1
表示函数的第一个参数。 这意味着Node
要求拥有第一个参数的所有权; 如果它由Lua拥有,则此所有权链现在断开,并且C ++现在拥有该对象。
就个人而言,我会说此API对Lua不利。 您似乎希望所有次要对象所有权都可以用C ++代码完成。 因此,Lua应该调用C ++函数来设置所有这些次要对象,而不必干预Lua。 Lua应该调用NodeManager
的成员函数以获取/创建Node
,然后应该调用将在该Node
创建Sprite
的函数。
Lua不必处理BoxObject
类的细节。 它不必直接创建Sprite
对象并将其放入Node
。
同样,个人而言,此API也不适合C ++ 。 如果Sprite
需要存储在某种容器中,并且该容器需要存储在某种Node
,那么创建Sprite
而不将其存储在容器中应该是不可能的。 这就是工厂功能的用途。 我什至不确定BoxObject
和CircleObject
的用途,因为Sprite
似乎正在做所有工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.