lua: lua 5.2.3 http://www.lua.org/download.html
book: http://www.lua.org/pil/contents.html#P1
code: http://www.troubleshooters.com/codecorn/lua/lua_c_calls_lua.htm
一、测试环境搭建
1.生成liblua.a静态库
(0) xocde new project选择
(1) OS X..Framework&Library..Library
(2) Framework:None(Plain C/C++ Library) .. Type:Static
(3) 把 lua-5.2.3/src 里的 C 文件引入到新建的 xcode 工程里
(4) build 工程,左边的状态栏 Products 目录下 libxxx.a 文件
libxxx.a 文件拖到终端查看此文件目录,cd 此目录open . 打开目录,拷贝 libxxx.a 文件
(5) 选中工程 Build Phases 将libxxx.a 添加到工程库里
2.建立测试工程
(0) xocde new project选择
(1) OS X..Application..Command Line Tool
(2) Language: C++
(3) 将 lua-5.2.3/src 里的文件拷贝到, main.cpp 目录下(libxxx.a 找不到头文件,实际上只用到 xxx.h文件)
真正用到的还是 libxxx.a 库。
二、lua C 交互
lua 和 C 交互通过抽象栈(先出后进,实际上一个指针控制 lua_State *L),栈顶到底(-1, -2, -3 ...),栈底到顶(1, 2, 3 ...)
函数:
lua_setglobal:lua 每次取此变量值都直接从lua解释器里取值,不需要通过解释器在访问 C 代码了(效率提升了)
lua_pushstring(L, "123")
lua_setglobal(L, "变量名")
lua: print(变量名) 输出 123
lua_settable:同 lua_setglobal 一样
(L,"MOUSE_X")
lua_pushnumber(L, 2)
lua_settable(L, idx)
lua_gettable(L, idx) 通过索引 idx 取 table 里的值
luaL_ref:返回栈中某个位置的索引,下次直接通过 lua_getref(L, index) 就能找到此值,相当于 key-value
int index =luaL_ref(L,-1)
lua_getref(L, index) 返回栈 -1 位置的值
luaL_unref(L, indxe) 记得释放
lua_gettop(L):栈元素个数
lua_settop(L, num):设置栈元素个数,num==0 栈清空
栈操作:
lua_pushvalue:把栈中指定索引的元素复制一份到栈顶
lua_remove:删除指定索引的元素
lua_insert:移动栈顶元素到指定索引的位置,栈中数目没有改变 lua_replace:从栈顶弹出元素值并将其设置到指定索引位置,栈中的数目减一 lua_checkstack:确保堆栈上至少有 extra 个空位。如果不能把堆栈扩展到相应的尺寸,函数返回 false 。这个函数永远不会缩小堆栈。 lua_pop:从栈顶弹出n个元素,它是一个lua_settop的包装:#define lua_pop(L,n) lua_settop(L, -(n)-1)
api参考:
1.加载 lua 文件
1.创建声明 lua
2. 打开 lua 库(否则 lua文件里 print 找不到)
3. 加载 lua 文件
4. 执行 lua 文件(加载 lua 里声明的全局变量或方法)
5. c 调用 lua (重点) 后面讲
6.关闭 lua 声明
#include <iostream>
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
void bail(lua_State *L, char *msg)
{
fprintf(stderr, "\nFATAL ERROR:\n %s: %s\n\n",
msg, lua_tostring(L, -1));
}
int main(int argc, const char * argv[])
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
if (luaL_loadfile(L, ".../LuaC/luaOne.lua"))
bail(L, "luaL_loadfile() failed");
if (lua_pcall(L, 0, 0, 0))
bail(L, "lua_pcall() failed");
/*
C 调用 lua 方法
*/
lua_close(L);
return 0;
}
2.调用 lua 方法
(1)获得 lua 的全局方法自动入栈
(2)传递的参数入栈
(3)执行调用 lua 的全局方法..之后..自动全部出栈
(4)lua 取出参数进行处理,返回参数给 C 自动入栈(此时栈已经空了)
(5)C 取出入栈的参数
(6)参数出栈需要手动
lua_pcall(L, 传lua参数个数, lua返回参数个数(一般1), 一般是0)
lua_getglobal(L, "square");
lua_pushnumber(L, 6);
lua_pcall(L, 1, 1, 0); //最好错误处理
int mynumber = lua_tonumber(L, -1);
lua_pop(L, 1);
3.参数和返回值 table 类型
(1)创建 table 自动放入栈顶
(2)push 一个key
(3)push一个value(栈元素位置value:-1、key:-2、table:-3)
(4)把 push 的 key 和 value 放到创建的 table 里,key value 自动出栈(此时栈里只有新建的 table)
(5)重复执行 (2) (3) (4)
(6)调用 lua 方法
lua_getglobal(L, "tweaktable");
lua_newtable(L);
lua_pushliteral(L, "fname");
lua_pushliteral(L, "Margie");
lua_settable(L, -3);
lua_pushliteral(L, "lname");
lua_pushliteral(L, "Martinez");
lua_settable(L, -3);
lua_pcall(L, 1, 1, 0);
(1)lua 返回的 table 自动入栈
(2)push 一个 nil 进栈(栈元素位置:nil:-1、返回的table:-2)
(3)判断 table 是否有元素,有:栈顶出栈(及-1位置出栈),key 入栈 value 入栈
栈元素位置(value:-1、key:-2、table:-3) 入栈出栈都是自动的
(4)取栈顶 value,value 出栈(手动),之后在取 key
(5)栈元素位置(key:-1、table:-2)
(6)回到 (3) 的操作 key 代替了之前的 nil
lua_pushnil(L);
const char *k, *v;
while (lua_next(L, -2))
{
v = lua_tostring(L, -1);
lua_pop(L,1);
k = lua_tostring(L, -1);
}
变量 table 里的table
void decode(lua_State *L)
{
const char *k, *v;
lua_pushnil(L);
while (lua_next(L, -2))
{
v = lua_tostring(L, -1);
if (lua_istable(L, -1))
{
decode(L);
lua_pop(L,1);
continue;
}
lua_pop(L,1);
k = lua_tostring(L, -1);
}
}
error:
注意:
性能:
参考:http://blog.codingnow.com/2006/01/_lua.html
一般调用过程,lua 调用解释器在通过解释器调用 C 做得操作,返回结果在通过解释器给lua (实际上都是在栈里操作)
1.有些经常用到的数据只调用一次 C 把结果放到解释器栈里,以后每次从解释器栈里取此数据
2.lua_pushstring 每次都要在栈里比较看是否有相同拷贝,没有创建新的拷贝。
经常用到的 string 设置一个索引,每次用这个索引直接从栈里取,省去了拷贝过程
3.每次都是 lua .. 解释器 .. C 程序,返回 C 程序 .. 解释器 .. lua
加载 lua 文件时返回一个方法给 C,C 可以直接在此方法里赋值省去了再次调用lua。
4.cocos2dx setPosition 专递的是 x y 两个 number 数字不是table,
这样能够提升性能官方说事 10 倍,setPosition 用得很频繁