zoukankan      html  css  js  c++  java
  • cocos2dx lua绑定解析

    花了几天时间看了下cocos2d-x lua绑定那块,总算是基本搞明白了,下面分三部分解析lua绑定:

    一、lua绑定主要用到的底层函数

    lua绑定其本质就是有一个公用的lua_Stack来进行C和Lua之间的值传递,在路径[项目根目录]\frameworks\cocos2d-x\external\lua\luajit\include下有个lua.h文件,大部分lua绑定底层函数以及相关的常量都在这里。

    1.lua堆栈常量

    #define LUA_REGISTRYINDEX (-10000)  //用于在C/C++中维持一些Lua对象
    #define LUA_ENVIRONINDEX (-10001)   //C/C++函数环境索引
    #define LUA_GLOBALSINDEX (-10002)  //全局变量_G的索引

    #define LUA_MINSTACK 20

    2.基础堆栈操作函数

    L是一个LIFO(先进后出)的堆栈,idx可以为负数,-1代表栈顶元素,以此类推

    LUA_API int (lua_gettop) (lua_State *L);        //获取栈顶元素的索引(值也等于堆栈中元素个数)
    LUA_API void (lua_settop) (lua_State *L, int idx);    //设置栈顶索引为idx,如果当前元素个数大于idx,则大于idx的元素被移除;如果当前元素个数小于idx,则用nil填充。另外,lua_settop(L, 0)用于清空堆栈。
    LUA_API void (lua_pushvalue) (lua_State *L, int idx);  //将堆栈中idx对应的元素拷贝一份到栈顶
    LUA_API void (lua_remove) (lua_State *L, int idx);    //移除idx对应的元素,并将其上面的元素依次下移来填充空白。
    LUA_API void (lua_insert) (lua_State *L, int idx);      //将栈顶元素插入到idx位置,原先在idx及上面的元素依次上移。
    LUA_API void (lua_replace) (lua_State *L, int idx);    //将栈顶元素弹出,并替换掉idx位置的元素
    LUA_API int (lua_checkstack) (lua_State *L, int sz);  //检测堆栈剩余的空间是否大于sz

    LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);//从 from 的堆栈中弹出 n 个值,然后把它们压入 to 的堆栈中。

    3.C访问堆栈函数(stack->C)

    LUA_API int (lua_isnumber) (lua_State *L, int idx);   //判断是否是number类型
    LUA_API int (lua_isstring) (lua_State *L, int idx);      //判断是否是string类型
    LUA_API int (lua_iscfunction) (lua_State *L, int idx);   //判断是否是CFunction类型
    LUA_API int (lua_isuserdata) (lua_State *L, int idx);  //判断是否是userdata类型

    LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);      //将堆栈元素转换为number类型
    LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx);       //将堆栈元素转换为integer类型
    LUA_API int (lua_toboolean) (lua_State *L, int idx);            //将堆栈元素转换为boolean类型
    LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);  //将堆栈元素转换为lstring类型
    LUA_API size_t (lua_objlen) (lua_State *L, int idx);            //将堆栈元素转换为size类型
    LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);    //将堆栈元素转换为CFunction类型
    LUA_API void *(lua_touserdata) (lua_State *L, int idx);          //将堆栈元素转换为userdata类型

    4.将C元素压入堆栈函数(C->stack)

    LUA_API void (lua_pushnil) (lua_State *L);                  //向堆栈压入nil
    LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);        //向堆栈压入number类型
    LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);        //向堆栈压入integer类型
    LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);     //向堆栈压入任意的char数组,允许包含'0'字符
    LUA_API void (lua_pushstring) (lua_State *L, const char *s);         //向堆栈压入char数组,必须以'0'结束
    LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);  //向堆栈压入fmt格式化后的string
    LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);   //向堆栈压入CFunction类型
    LUA_API void (lua_pushboolean) (lua_State *L, int b);             //向堆栈压入boolean类型
    LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);        //向堆栈压入C指针的值

    5.将堆栈元素存入lua表(stack->Lua)

    LUA_API void (lua_settable) (lua_State *L, int idx);        //向lua表存入table类型

    e.g:
    lua_pushnumber(L, 1);
    lua_pushstring(L, "1");
    lua_settable(L, -3);

    LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); //向lua表设置key-CFunction对

    e.g:
    lua_pushcfunction(L, l_sin);
    lua_setfield(L, LUA_GLOBALSINDEX, "mysin");

    LUA_API void (lua_rawset) (lua_State *L, int idx);        //向lua表设置变量值

    e.g:
    lua_pushstring(L, "tolua_opened");
    lua_pushboolean(L, 1);
    lua_rawset(L, LUA_REGISTRYINDEX)

    LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);     //向lua表设置变量值,n作为key
    e.g:

    lua_pushstring(L, "1");
    lua_rawseti(L, -2, 1);

    等同于

    lua_pushnumber(L, 1);

    lua_pushstring(L, "1");

    lua_settable(L, -3);

    LUA_API int (lua_setmetatable) (lua_State *L, int objindex);    //设置元表

    e.g:
    lua_createtable(L, 0, 0);//表A
    lua_createtable(L, 0, 0);//表B
    lua_pushnumber(L, 1);
    lua_pushstring(L, "1");
    lua_rawset(L, -3);
    lua_setmetatable(L, -2);//表B成为表A的元表

    6.从lua表中获取函数(Lua->stack)

    作用是(5)中函数的逆运算,用法同上

    LUA_API void (lua_gettable) (lua_State *L, int idx);          
    LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);    
    LUA_API void (lua_rawget) (lua_State *L, int idx);          
    LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
    LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);    //新建一个lua表
    LUA_API int (lua_getmetatable) (lua_State *L, int objindex);

    二、lua绑定流程

    1.C中注册类

    在工程中新建了一个简单的类UNode,其中有2个主要方法create和getTag

    2.C中注册方法

    a).首先在AppDelegate.cpp的applicationDidFinishLaunching中加入绑定代码

    b).定义BindingManager中bind方法

    c).新建lua_uuf_auto类,定义register_all_cocos2dx_uuf方法,该方法在_G中注册了一个uuf的模块

    d).继续在类中定义lua_register_cocos2dx_uuf_UNode方法,该方法注册了2个UNode方法,create和getTag,分别对应lua_cocos2dx_uuf_UNode_create、lua_cocos2dx_uuf_UNode_getTag方法

    e).最后,实现create、getTag方法。

    create方法接受的参数是UNode表,通过UNode:create()得到一个UNode实例ret,然后将其转为luaval压入堆栈。

    getTag方法接受的参数是一个lua类型的UNode实例,然后将其转为C中的UNode实例,并调用getTag方法,最后将结果ret压入堆栈。

    三、Lua中调用

     现在准备工作已经完成,我们来检测下刚才注册的方法是否有效

    在Lua主线程入口src/main.lua的main方法中加入:

    local node = uuf.UNode:create();    --获得一个UNode实例

    cclog("tag:"..node:getTag());      --控制台输出"tag:200"

    这个输出就是UNode.h中定义的getTag返回的200,到此一个完整的lua调用C方法的流程完成。

  • 相关阅读:
    关于xmlhttprequest的readystate属性的五个状态(转载)
    MySQL在windows下 1045 access denied for user 'root'@'localhost' using password yes 解决办法 (转)
    栈 堆
    代码安全问题
    TSQL 编程规范(摘自网络)
    UCenter 来自网络
    如何调试 asp 程序 摘自: http://hi.baidu.com/artmis_/blog/item/dd859df57c317b7edcc474f0.html
    《大话设计模式》6个原则 转帖
    SliverLight的bug OR Vs2008的bug?
    ifconfig
  • 原文地址:https://www.cnblogs.com/Pickcle/p/5049467.html
Copyright © 2011-2022 走看看