菜鸟入门之lua与c++相互调用(包含多个demo)

c++与lua直接的调用,实际上通过一个栈结构来传递数据,该栈结构栈顶的索引值为-1,向栈底方向索引值依次为-1 ,-2......栈顶索引为1.栈结构里可以放函数,表,字符串,整形等各种lua的基本数据。

一、在当前cpp目录下创建test.lua文件,用于与c++交互调用,代码如下:


  1. print("hello world from lua file")
  2. table1 = {}
  3. table1["dinner"] = "rice"
  4. table1["hahha"] = "ri123ce"
  5. gScreenW = 1280;
  6. function getIntegerSumFuncs(a ,b)
  7. <span style="white-space:pre"></span>return a + b
  8. end
  9. avg ,sum = average(10 ,20 ,30 ,40 ,50)

二、先熟悉下lua常用的C语言API。

int luaL_dofile (lua_State *L, const char *filename);//运行lua文件,L是当前已经创建的栈结构。返回0,运行文件正常;返回1,代表出现异常。

void lua_setglobal (lua_State *L, const char *name);//从堆栈上弹出一个值,并将其设到全局变量 name 中

void lua_getglobal (lua_State *L, const char *name);//把全局变量 name 里的值压入堆栈,栈顶值为-1。

const char *lua_tostring (lua_State *L, int index);//在栈L的索引值为index处取值并转化成C字符串(lua_tointeger等类似)

void lua_settop (lua_State *L, int index);//参数允许传入任何可接受的索引以及 0。它将把堆栈的栈顶设为这个索引。 如果新的栈顶比原来的大,超出部分的新元素将被填为 nil 。 如果 index 为 0 ,把栈上所有元素移除。

int lua_gettop (lua_State *L);//返回堆栈上的元素个数(返回 0 表示堆栈为空)

int lua_next (lua_State *L, int index);从栈上弹出一个 key(键), 然后把索引指定的表中 key-value(健值)对压入堆栈 (指定 key 后面的下一 (next) 对)。 如果表中以无更多元素, 那么 lua_next 将返回 0 (什么也不压入堆栈)。

void lua_pushinteger (lua_State *L, lua_Integer n);//把 n 作为一个数字压栈。

void lua_close (lua_State *L);//销毁指定 Lua 状态机中的所有对象

如果需要查询其他函数,推荐到Lua 5.1 参考手册,很详细也比较准确。

三、c++获取lua中的全局字符串。


  1. //获取lua全局string
  2. const char* getLuaGlobalString(char *fileName ,char *varName)
  3. {
  4. lua_State *L = lua_open();
  5. luaL_openlibs(L);
  6. //加载并运行test.lua文件
  7. int isOpen = luaL_dofile(L ,fileName);
  8. if (isOpen == 0) {
  9. printf("error loading lua");
  10. }
  11. //将栈顶的索引设置为该index,如果index传0,移除栈上所有元素
  12. lua_settop(L ,0);
  13. //把全局变量 allGlobalChar 里的值压入堆栈。
  14. char *allGlobalChar = varName;
  15. lua_getglobal(L ,allGlobalChar);
  16. int stateCode = lua_isstring(L ,1);
  17. if (stateCode != 1) {
  18. printf("open lua error code:%d" ,stateCode);
  19. return NULL;
  20. }
  21. const char* s = lua_tostring(L ,1);
  22. printf("get global screenW is:%s " ,s);
  23. lua_pop(L ,1);
  24. lua_close(L);
  25. return s;
  26. }

调用代码:getLuaGlobalString("test.lua" ,"gScreenW");

四、c++获取lua table中的的值


  1. const char* getLuaVarOfTable(const char *fileName,const char *tableName ,const char *keyName)
  2. {
  3. lua_State *L = lua_open();
  4. luaL_openlibs(L);
  5. int isOpen = luaL_dofile(L ,fileName);
  6. if (isOpen != 0)
  7. {
  8. printf("error open lua file");
  9. return NULL;
  10. }
  11. lua_settop(L ,0);//清空栈
  12. lua_getglobal(L ,tableName);
  13. int stateCode = lua_istable(L ,-1);//取栈顶
  14. if (stateCode != 1)
  15. {
  16. printf("get table failed code:%d" ,stateCode);
  17. return NULL;
  18. }
  19. lua_pushstring(L ,keyName);
  20. lua_gettable(L ,-2); //取栈顶下一个元素
  21. const char* valueStr = lua_tostring(L ,-1); //取栈顶
  22. printf("get lua table key-value %s-%s" ,keyName ,valueStr);
  23. lua_pop(L ,-1);
  24. return valueStr;
  25. }

调用代码:getLuaVarOfTable("test.lua" ,"table1" ,"dinner");

五、c++获取获取lua中的表


  1. <pre name="code" class="java">string getLuaVarTable(const char* fileName ,const char *tableName ,char *result)
  2. {
  3. lua_State *L = lua_open();
  4. luaL_openlibs(L);
  5. int isOpen = luaL_dofile(L ,fileName);
  6. if (isOpen != 0)
  7. {
  8. printf("error open lua file");
  9. return NULL;
  10. }
  11. lua_getglobal(L ,tableName);
  12. int size = lua_gettop(L);
  13. lua_pushnil(L);
  14. int index = 0;
  15. while(lua_next(L ,size))
  16. {
  17. const char* key = lua_tostring(L ,-2);//取栈顶下一个元素
  18. const char* value = lua_tostring(L , -1); //取栈顶
  19. //使用memcpy ,index记录地址游标
  20. memcpy(&result[index] ,key ,strlen(key));
  21. index += strlen(key);
  22. //因为sizeof取字符串,最后会有"/0"占一个字节,所以应该减去1
  23. memcpy(&result[index] ,"-" ,sizeof("-") - 1);
  24. index += 1;
  25. memcpy(&result[index] ,value ,strlen(value));
  26. index += strlen(value);
  27. lua_pop(L ,1);
  28. }
  29. result[index] = 0;
  30. cout <<"result is " << result << endl;
  31. //free(result);
  32. //printf("---%s" ,result.c_str);
  33. lua_pop(L ,1);
  34. return result;
  35. }
  36. 调用代码:
  37. char* reslut = (char*)malloc(100 * sizeof(char));
  38. getLuaVarTable("test.lua" ,"table1" ,reslut);
  39. free(reslut);

六、cpp调用lua中的函数


  1. //要调用一个函数请遵循以下协议: 首先,要调用的函数应该被压入堆栈;
  2. //接着,把需要传递给这个函数的参数按正序压栈; 这是指第一个参数首先压栈。
  3. //最后调用一下 lua_call; nargs 是你压入堆栈的参数个数。
  4. //当函数调用完毕后,所有的参数以及函数本身都会出栈。 而函数的返回值这时则被压入堆栈。
  5. //返回值的个数将被调整为 nresults 个, 除非 nresults 被设置成 LUA_MULTRET。
  6. //在这种情况下,所有的返回值都被压入堆栈中。 Lua 会保证返回值都放入栈空间中。
  7. //函数返回值将按正序压栈(第一个返回值首先压栈), 因此在调用结束后,最后一个返回值将被放在栈顶。
  8. const char* callLuaFunc(const char* fileName ,const char* functionName)
  9. {
  10. lua_State *L = lua_open();
  11. luaL_openlibs(L);
  12. int isOpen = luaL_dofile(L ,fileName);
  13. if (isOpen != 0) {
  14. printf("error open lua file %s" ,fileName);
  15. return NULL;
  16. }
  17. lua_getglobal(L ,functionName);//如果表和函数重名,会怎么样
  18. lua_pushinteger(L ,12);
  19. lua_pushinteger(L ,3);
  20. //第一个参数:函数的个数 第二个参数:函数的返回值个数
  21. lua_call(L ,2 ,1);
  22. int result = lua_tointeger(L ,-1);
  23. printf("call lua func result : %d" ,result);
  24. return NULL;
  25. }

调用代码:callLuaFunc("test.lua" ,"getIntegerSumFuncs");

七、lua调用cpp函数计算平均值


  1. //cpp计算平均值的函数
  2. int average(lua_State* L)
  3. {
  4. int n = lua_gettop(L);
  5. double sum = 0;
  6. int i;
  7. for (i = 1; i <= n; i ++)
  8. {
  9. if (!lua_isnumber(L ,i))
  10. {
  11. lua_pushstring(L ,"incorrect argument to avg");
  12. lua_error(L);
  13. }
  14. sum += lua_tonumber(L ,i);
  15. }
  16. lua_pushnumber(L ,sum / n);
  17. lua_pushnumber(L ,sum);
  18. //这里一定要返回元素个数,若返回0则找不到结果
  19. return 2;
  20. }
  21. //lua调用cpp计算平均值,调用入口
  22. int averageMain()
  23. {
  24. lua_State* L = lua_open();
  25. luaL_openlibs(L);
  26. //注册lua函数,实际上是将average push到栈结构,然后set average函数为global函数
  27. lua_register(L ,"average" ,average);
  28. //运行脚本
  29. luaL_dofile(L ,"test.lua");
  30. //把全局变量 avg 里的值压入堆栈
  31. lua_getglobal(L ,"avg");
  32. // 栈顶是-1,栈底是1
  33. cout << "cpp show: avg is " << lua_tointeger(L ,-1) <<endl;
  34. //从栈中弹出一个元素
  35. //lua_pop(L ,1);
  36. //把全局变量 sum 里的值压入堆栈
  37. lua_getglobal(L ,"sum");
  38. cout << "cpp show: sum is " << lua_tointeger(L ,-1) <<endl;
  39. //清除栈结构
  40. lua_close(L);
  41. return 0;
  42. }

代码调用:

averageMain();

以上是c++和lua调用常用的demo。

这里附上工程实例下载地址: http://download.csdn.net/detail/wangbin_jxust/7809743

如果需要运行该工程,需要按照使用vs2010编译lua5.1源码生成lua.lib 配置一遍,然再运行。

菜鸟入门之lua与c++相互调用(包含多个demo)

相关推荐