Dae*_*rst 6 c++ mapping variables lua pointers
我正在使用Lua在C++中使用游戏引擎来定义NPC.
我可以像这样定义一个原型NPC:
orc =
{
name = "Generic Orc",
health = 100
}
function orc:onIdle()
print("Orc idles...")
end
Run Code Online (Sandbox Code Playgroud)
然后使用生成"Orc"的实例entitySpawn(orc)
.这是一个C++函数,它从给定的表中读取健康和名称等值,使用给定的值在C++中创建一个Entity对象,另外为特定的NPC创建一个Lua表.
现在,我想orc.health
在Lua中的mHealth
变量和C++中相应的Entity对象的成员变量之间建立直接连接,因此我可以在Lua中分配一个值并立即在C++中使用它,反之亦然.
这甚至可能吗?或者我是否必须使用setter/getter函数?我已经看了一下light userdata并且已经到了在Lua中存储指向C++变量的指针,但无法分配值.
这个有可能.我假设它entitySpawn
返回C++为实体创建的表.我还假设您可以从C++中公开一个函数,该函数接受实体的表并返回当前的运行状况,类似于设置.(您可以使用指向C++对象的light userdata指针作为此表的成员来实现此功能.)
所以丑陋的方式看起来像这样:
local myOrc = entitySpawn(orc)
local curHealth = getEntityHealth(myOrc)
setEntityHealth(myOrc, curHealth + 10)
Run Code Online (Sandbox Code Playgroud)
为了使这个更漂亮,我们可以与metatables有一些乐趣.首先,我们将为我们关心的所有属性设置访问器.
entityGetters = {
health = getEntityHealth,
-- ...
}
entitySetters = {
health = setEntityHealth,
-- ...
}
Run Code Online (Sandbox Code Playgroud)
然后我们将创建一个使用这些函数来处理属性赋值的元表.
entityMetatable = {}
function entityMetatable:__index(key)
local getter = entityGetters[key]
if getter then
return getter(self)
else
return nil
end
end
function entityMetable:__newindex(key, value)
local setter = entitySetters[key]
if setter then
return setter(self, value)
end
end
Run Code Online (Sandbox Code Playgroud)
现在你需要entitySpawn
分配metatable.您可以使用该lua_setmetatable
功能执行此操作.
int entitySpawn(lua_State* L)
{
// ...
// assuming that the returned table is on top of the stack
lua_getglobal(L, "entityMetatable");
lua_setmetatable(L, -2);
return 1;
}
Run Code Online (Sandbox Code Playgroud)
现在你可以用很好的方式编写它:
local myOrc = entitySpawn(orc)
myOrc.health = myOrc.health + 10
Run Code Online (Sandbox Code Playgroud)
请注意,这需要由返回的表entitySpawn
确实不具有健康属性集.如果确实如此,则永远不会为该属性咨询metatable.
您可以创建entityGetters
,entitySetters
和entityMetatable
表,以及在__index
和__newindex
元方法,在C++而不是Lua中如果感觉清洁给你,但总的想法是一样的.