2010-04-20 85 views
4

我对Lua相当陌生,我一直在努力实现Lua脚本编写逻辑,我将它放在一个游戏引擎中。到目前为止,我没有遇到任何麻烦让Lua通过引擎运行,我可以从Lua的C和C函数调用Lua函数。我将如何去与Lua共享C++类中的变量?

现在引擎工作的方式,每个Object类都包含一组变量,引擎可以快速迭代以绘制或处理物理过程。虽然游戏对象都需要访问和操作这些变量,以便游戏引擎本身能够看到任何变化,但他们可以自由创建自己的变量,Lua对此非常灵活,所以我不担心任何问题。无论如何,目前游戏引擎方面的东西都坐在C陆地上,我真的希望他们呆在那里,因为性能方面的原因。所以在一个理想的世界里,当产生一个新的游戏对象时,我需要能够让Lua读/写这个标准变量集作为Lua对象基类的一部分,然后它的游戏逻辑可以继续狂奔着。到目前为止,我保留了两个独立的对象表 - Lua生成一个新的游戏对象,它将自身添加到一个数字索引的全局对象表中,然后继续调用C++函数,该函数创建一个新的GameObject类,并在类中注册Lua索引(一个int)。到目前为止,C++函数现在可以看到Lua对象,并轻松地使用dostring在Lua land中执行操作或调用函数。

我现在需要做的是将C++变量作为GameObject类的一部分,并将它们暴露给Lua,这就是Google让我失败的原因。我遇到了一个非常好的方法here,它详细介绍了使用标签的过程,但是我已经读过这种方法已被弃用,以支持metatables。

完成此操作的理想方法是什么?学习如何使用libBind或一些等价的方法传递类定义是否值得学习,或者是否有一种简单的方法,我可以将全局lua对象注册到每个变量(一次,在产卵时)?从Lua 5.1.4开始,什么是“当前”最好的方法呢?

回答

4

一种方法是使用

  • 一个lightuserdata指向C++可变
  • C函数使用lightuserdata
  • 访问C++变量保持lightuserdata作为C的函数的的upvalue所以一个函数满足所有变量
  • 使用函数的参数数量来获取和设置变量之间进行选择

例如:

int game_state_var_accessor (lua_State *L) 
{ 
    int *p = lua_topointer(L, lua_upvalueindex(1)); 
    if (lua_gettop(L) == 0) 
    { // stack empty, so get 
     lua_pushinteger(L, *p); 
     return 1; 
    } 
    else 
    { // arg provided, so set 
     *p = lua_tointeger(L,1); 
     return 0; 
    } 
} 

当你犯了一个新的游戏状态就可以使用创建每个变量的访问器:

lua_pushlightuserdata(L, (int *)p); // where p points to your variable 
lua_pushcclosure(L, game_state_var_accessor, 1); 

现在的访问是在栈上,并可以绑定到一个全局名称或Lua类中方法的名称。如果你的Lua类表是在栈上的索引t这将是:

lua_setfield(L, t, "name_of_accessor"); 
+0

问:你投的指针,P,与(int *),但在文档中lua_pushlightuserdata接受(无效*)。除了代码可读性以外,是否有任何好处以这种方式投射?我想我会需要为不同类型的变量创建单独的包装函数,它似乎有点奇怪。 – 2010-04-24 06:05:23

+0

演员只在那里突出显示与返回类型game_state_var_accessor的对应关系;换句话说,为了可读性。如果您正在为其他类型的包装器进行制作,则可以将其重命名为game_state_int_accessor以保持完整。 – 2010-04-24 13:40:24

+0

这个解决方案工作得很好。非常感谢!是的,我结束了使用不同的粘合剂功能,因为每个需要一个不同的处理函数。 我还在这里学习,但Lua的通信API是*纯粹的天才*,我很喜欢它。^_^ – 2010-04-29 18:24:16