Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
检测陈旧的C++;Lua中的引用 我是一个主要用C++编写的游戏,但是使用LUA来编写机器人的脚本。我们正在使用(Luna的一种变体)将碎片粘在一起 我现在正在苦苦思索我们的Lua脚本如何知道他们引用的对象已经被C++代码删除了。_C++_Lua - Fatal编程技术网

检测陈旧的C++;Lua中的引用 我是一个主要用C++编写的游戏,但是使用LUA来编写机器人的脚本。我们正在使用(Luna的一种变体)将碎片粘在一起 我现在正在苦苦思索我们的Lua脚本如何知道他们引用的对象已经被C++代码删除了。

检测陈旧的C++;Lua中的引用 我是一个主要用C++编写的游戏,但是使用LUA来编写机器人的脚本。我们正在使用(Luna的一种变体)将碎片粘在一起 我现在正在苦苦思索我们的Lua脚本如何知道他们引用的对象已经被C++代码删除了。,c++,lua,C++,Lua,以下是一些机器人示例代码(在Lua中): 请注意,仅当needTarget为true时才设置ship,否则将使用来自上一次迭代的值。自上次设置变量以来,很有可能(甚至,如果bot一直在做它的工作:-),飞船已经被杀死(并且它的对象被C++删除)。如果是这样,C++将在调用St:GeLoCo()时有一个合适的值,并且通常会崩溃。 因此,问题是如何最优雅地处理这种情况,并在程序员出错时限制损害 我有一些想法。首先,我们可以创建某种类型的Lua函数,C++代码在船或其他项死亡时调用它: functio

以下是一些机器人示例代码(在Lua中):

请注意,仅当needTarget为true时才设置ship,否则将使用来自上一次迭代的值。自上次设置变量以来,很有可能(甚至,如果bot一直在做它的工作:-),飞船已经被杀死(并且它的对象被C++删除)。如果是这样,C++将在调用St:GeLoCo()时有一个合适的值,并且通常会崩溃。 因此,问题是如何最优雅地处理这种情况,并在程序员出错时限制损害

我有一些想法。首先,我们可以创建某种类型的Lua函数,C++代码在船或其他项死亡时调用它:

function itemDied(deaditem)
    if deaditem == ship then
        ship = nil
        needTarget = true
    end
end
其次,我们可以实现某种引用计数智能指针来“神奇地”解决问题。但我不知道从哪里开始

第三,我们可以有某种死区检测器(不确定如何工作),机器人可以这样调用:

if !isAlive(ship) then
    needTarget = true
    ship = nil             -- superfluous, but here for clarity in this example
end

if needTarget then                           -- needTarget => global(?) boolean
    ship = findClosest(findItems(ShipType))  -- ship => global lightUserData obj
end

<...as before...>
if!我住在船上
needTarget=true
ship=nil——多余,但为了在本例中更清楚起见
结束
如果需要目标,则--needTarget=>global(?)boolean
ship=findClosest(findItems(ShipType))--ship=>global lightUserData obj
结束
第四,我只能保留船的ID,而不是引用,并使用该ID在每个周期获取船对象,如下所示:

local ship = getShip(shipID)                 -- shipID => global ID

if ship == nil then
    needTarget = true
end

if needTarget then                           -- needTarget => global(?) boolean
    ship = findClosest(findItems(ShipType))  -- ship => global lightUserData obj
    shipID = ship:getID()
end

<...as before...>
localship=getShip(shipID)——shipID=>global ID
如果ship==nil,则
needTarget=true
结束
如果需要目标,则--needTarget=>global(?)boolean
ship=findClosest(findItems(ShipType))--ship=>global lightUserData obj
shipID=ship:getID()
结束
我的理想情况也是明智地抛出错误。如果我在一艘死船上运行getLoc()方法,我希望触发错误处理代码,让机器人有机会恢复,或者至少让系统杀死机器人并记录问题,希望提醒我在编写机器人代码时要更加小心

这些是我的想法。我倾向于#1,但它感觉很笨重(可能会涉及很多来回,因为我们有很多像子弹这样的短生命周期对象要处理,其中大部分我们不会跟踪)。可能很容易忘记实现itemdired()函数#2很吸引人,因为我喜欢魔术,但不知道它是如何工作的#3非常容易理解,我可以将我的死区检测限制在几个游戏周期(最有可能是一艘飞船)内感兴趣的少数对象上

这一定是一个常见的问题。你觉得这些想法怎么样?还有更好的吗

谢谢


以下是我目前的最佳解决方案:

在C++中,我的船对象被称为Stand,其生命周期由C++控制。对于每个Ship,我创建一个称为LuaShip的代理对象,它包含一个指向Ship的指针,Ship包含一个指向LuaShip的指针。在飞船的析构函数中,我将LuaShip的飞船指针设置为NULL,我将其用作飞船已被摧毁的指示器

我的Lua代码只有一个对LuaShip的引用,因此(至少在理论上,由于这部分仍然不能正常工作),Lua将在相应的Ship对象消失后控制LuaShip的生命周期。所以Lua总是有一个有效的句柄,即使在Ship对象消失之后,我也可以为Ship方法编写代理方法来检查Ship是否为NULL

因此,现在我的任务是更好地理解Luna/Lunar如何管理指针的生命周期,并确保我的Luaship不会在其合作伙伴飞船被删除时被删除,如果仍然有一些Lua代码指向它们。这应该是非常可行的


事实上,这是行不通的(至少我是行不通的)。似乎起作用的是将飞船和卢阿希普物体稍微分离。现在,当Lua脚本请求一个LuaShip对象时,我创建一个新对象并将其交给Lua,然后让Lua在处理完它后删除它。LuaShip使用一个智能指针来引用飞船,因此当飞船死亡时,该指针被设置为NULL,LuaShip对象可以检测到该值

使用前,由Lua编码器检查船舶是否仍然有效。如果他们不这样做,我就可以抓住这个位置,抛出一条严厉的错误信息,而不是让整个游戏崩溃(就像以前发生的那样)

现在,Lua已经完全控制了Luasip的生命周期,C++可以删除船只而不会造成问题,而且一切都看起来很顺利。唯一的缺点是我可能会创建很多LuaShip对象,但实际上并没有那么糟糕


如果您对这个主题感兴趣,请参阅我发布的关于一个相关概念的邮件列表线程,该线程以完善上述内容的一些建议结尾:


我们公司采用了第四种解决方案,对我们来说效果很好。我推荐它。但是,为了完整性:

1号是实心的。让飞船的析构函数调用一些月球代码(或者标记它无论如何都应该被调用),然后如果你找不到它就抱怨。这样做意味着您必须非常小心,如果您想在单独的线程中运行游戏引擎和机器人,可能需要稍微修改Lua运行时

第2号并不像你想象的那么难:在C++侧写或借用一个引用计数指针,如果你的Lua /C++胶习惯于处理C++指针,它可能会不需要进一步的干预而工作,除非你正在生成。

local ship = getShip(shipID)                 -- shipID => global ID

if ship == nil then
    needTarget = true
end

if needTarget then                           -- needTarget => global(?) boolean
    ship = findClosest(findItems(ShipType))  -- ship => global lightUserData obj
    shipID = ship:getID()
end

<...as before...>
if ship==nil or ship.destroyed then
  ship = findClosest(findItems(ShipType))
end