C编程语言嵌入Lua的用法

来源:互联网 发布:怎么查看端口是否开放 编辑:程序博客网 时间:2024/06/06 16:48

C编程语言嵌入Lua的用法


当你希望在你的游戏开始的时候读取一些信息,以配置你的游戏,这些信息通常都是放到一个文本文件中,在你的游戏启动的时候,你需要打开这个文件,然后解析字符串,找到所需要的信息。


    是的,或许你认为这样就足够了,为什么还要使用Lua呢?

    应用于“配置”这个目的,Lua提供给你更为强大,也更为灵活的表达方式,在上一种方式中,你无法根据某些条件来配置你的游戏,Lua提供给你灵活的表达方式,你可以类似于这样来配置你的游戏:

[cpp] view plain copy print?
  1. if player:is_dead() then  
  2. do_something()  
  3. else  
  4. do_else()  
  5. end  


更为重要的是,在你做了一些修改之后,完全不需要重新编译你的游戏代码。


通常,在游戏中你并不需要一个单独的解释器,你需要在游戏来运行解释器,下面,让我们来看看,如何在你的代码中运行解释器:

[cpp] view plain copy print?
  1. //这是lua所需的三个头文件  
  2. //当然,你需要链接到正确的lib  
  3.   
  4. extern "C"  
  5.   
  6. {  
  7. #include "lua.h"  
  8. #include "lauxlib.h"  
  9. #include "lualib.h"  
  10.   
  11.   
  12. }  
  13.   
  14.   
  15. int main(int argc, char *argv[])  
  16. {  
  17. lua_State *L = lua_open();  
  18.   
  19. // 此处记住,当你使用的是5.1版本以上的Lua时,请修改以下两句为luaL_openlibs(L);  
  20. luaopen_base(L);   
  21. luaopen_io(L);  
  22.   
  23. const char *buf = "print('hello, world!')";  
  24.   
  25. // 记住,当你使用的是5.1版本以上的Lua时请使用luaL_dostring(L,buf);  
  26.   
  27. lua_dostring(buf);  
  28.   
  29. lua_close(L);  
  30.   
  31. return 0;  
  32. }  




程序输出:hello, world!


有时你需要执行一段字符串,有时你可能需要执行一个文件,当你需要执行一个文件时,你可以这么做:
lua_dofile(L, "test.lua");


看,非常简单吧。




取得信息


下面让我们来看看如何从脚本中取得我们所需要的信息。


 
首先,让我来简单的解释一下Lua解释器的工作机制,Lua解释器自身维护一个运行时栈,通过这个运行时栈,Lua解释器向主机程序传递参数,所以我们可以这样来得到一个脚本变量的值:

[cpp] view plain copy print?
  1. <span style="font-family:'Microsoft YaHei';font-size:16px;">lua_pushstring(L, "var"); //将变量的名字放入栈  
  2. lua_gettatbl(L, LUA_GLOBALSINDEX);变量的值现在栈顶</span>  

假设你在脚本中有一个变量 var = 100

你可以这样来得到这个变量值:

[cpp] view plain copy print?
  1. int var = lua_tonumber(L, -1);  

怎么样,是不是很简单?


Lua定义了一个宏让你简单的取得一个变量的值:
[cpp] view plain copy print?
  1. lua_getglobal(L, name)  


我们可以这样来取得一个变量的值:

[cpp] view plain copy print?
  1. lua_getglobal(L, "var"); //变量的值现在栈顶  
  2. int var = lua_tonumber(L, -1);  
[cpp] view plain copy print?
  1.   

完整的测试代码如下:

[cpp] view plain copy print?
  1. #include "lua.h"  
  2. #inculde "lauxlib.h"  
  3. #include "lualib.h"  
  4.   
  5.   
  6. int main(int argc, char *argv[])  
  7. {  
  8. lua_State *L = lua_open();  
  9.   
  10.   
  11. // 此处记住,当你使用的是5.1版本以上的Lua时,请修改以下两句为luaL_openlibs(L);  
  12. luaopen_base(L);  
  13. luaopen_io(L);  
  14.   
  15. const char *buf = "var = 100";  
  16.   
  17.   
  18. lua_dostring(L, buf);  
  19.   
  20.   
  21. lua_getglobal(L, "var");  
  22. int var = lua_tonumber(L, -1);  
  23.   
  24.   
  25. assert(var == 100);  
  26.   
  27.   
  28. lua_close(L);  
  29.   
  30.   
  31. return 0;  
  32. }   


调用函数


假设你在脚本中定义了一个函数:
[cpp] view plain copy print?
  1. function main(number)  
  2. number = number + 1  
  3. return number  
  4. end  



在你的游戏代码中,你希望在某个时刻调用这个函数取得它的返回值。


在Lua中,函数等同于变量,所以你可以这样来取得这个函数:
[cpp] view plain copy print?
  1. lua_getglobal(L, "main");//函数现在栈顶  



现在,我们可以调用这个函数,并传递给它正确的参数:

[cpp] view plain copy print?
  1. <span style="font-family:'Microsoft YaHei';">lua_pushnumber(L, 100); //将参数压栈  
  2. lua_pcall(L, 1, 1, 0); //调用函数,有一个参数,一个返回值  
  3. //返回值现在栈顶  
  4. int result = lua_tonumber(L, -1);</span>  


result 就是函数的返回值


完整的测试代码如下:

[cpp] view plain copy print?
  1. #include "lua.h"  
  2. #include "lauxlib.h"  
  3. #include "lualib.h"  
  4.   
  5. int main(int argc, char *argv[])  
  6. {  
  7. lua_State *L = lua_open();  
  8.   
  9.   
  10. // 此处记住,当你使用的是5.1版本以上的Lua时,请修改以下这句为luaL_openlibs(L);  
  11. luaopen_base(L);  
  12.   
  13. const char *buf = "function main(number) number = number + 1 return number end";  
  14.   
  15. lua_dostring(buf);  
  16.   
  17. lua_getglobal(L, "main");  
  18. lua_pushnumber(L, 100);  
  19. lua_pcall(L, 1, 1, 0);  
  20.   
  21. int result = lua_tonumber(L, -1);  
  22.   
  23. assert(result == 101);  
  24.   
  25. lua_close(L);  
  26.   
  27. return 0;  
  28. }  




脚本调用程序



Lua本身定位在一种轻量级的,灵活的,可扩充的脚本语言,这意味着你可以自由的扩充Lua,为你自己的游戏量身定做一个脚本语言。



你可以在主机程序中向脚本提供你自定的api,供脚本调用。


Lua定义了一种类型:lua_CFunction,这是一个函数指针,它的原型是:
typedef int (*lua_CFunction) (lua_State *L);


这意味着只有这种类型的函数才能向Lua注册。


首先,我们定义一个函数


[cpp] view plain copy print?
  1. int foo(lua_State *L)  
  2. {  
  3. //首先取出脚本执行这个函数时压入栈的参数  
  4. //假设这个函数提供一个参数,有两个返回值  
  5.   
  6. //get the first parameter  
  7. const char *par = lua_tostring(L, -1);  
  8.   
  9. printf("%s/n", par);  
  10.   
  11. //push the first result  
  12. lua_pushnumber(L, 100);  
  13.   
  14. //push the second result  
  15. lua_pushnumber(L, 200);  
  16.   
  17. //return 2 result  
  18. return 2;  
  19. }  
  20.   
  21. 我们可以在脚本中这样调用这个函数  
  22.   
  23. r1, r2 = foo("hello")  
  24.   
  25. print(r1..r2)  


完整的测试代码如下:

[cpp] view plain copy print?
  1. extern "C"  
  2.   
  3. {  
  4. #include "lua.h"  
  5. #include "lauxlib.h"  
  6. #include "lualib.h"  
  7. }  
  8.   
  9. int foo(lua_State *L)  
  10. {  
  11. //首先取出脚本执行这个函数时压入栈的参数  
  12. //假设这个函数提供一个参数,有两个返回值  
  13.   
  14. //get the first parameter  
  15. const char *par = lua_tostring(L, -1);  
  16.   
  17. printf("%s/n", par);  
  18.   
  19. //push the first result  
  20. lua_pushnumber(L, 100);  
  21.   
  22. //push the second result  
  23. lua_pushnumber(L, 200);  
  24.   
  25. //return 2 result  
  26. return 2;  
  27. }  
  28.   
  29. int main(int argc, char *argv[])  
  30. {  
  31. lua_State *L = lua_open();  
  32.   
  33.   
  34. // 此处记住,当你使用的是5.1版本以上的Lua时,请修改以下两句为luaL_openlibs(L);  
  35. luaopen_base(L);  
  36. luaopen_io(L);  
  37.   
  38. lua_register(L, "foo", foo);  
  39.   
  40. const char *buf = "r1, r2 = foo("hello") print(r1..r2)";  
  41.   
  42. lua_dostring(L, buf);  
  43.   
  44. lua_close(L);  
  45.   
  46. return 0;  
  47. }  


程序输出:

hello
100200
0 0
原创粉丝点击