cocos2d-x 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方法的流程完成。

时间: 2024-10-13 07:05:47

cocos2d-x lua绑定解析的相关文章

使用cocos2d脚本生成lua绑定

这几天要老大要求把DragonBones移到cocos2dx 3.0 里边,并且绑定lua使用接口.因为刚学lua,使用的引擎也刚从2.2改为3.0,各种不熟悉,折腾了好几天才弄完,有空了总结一下 这篇先说一下cocos2d生成lua绑定的修改,有空的话再写一篇lua中注册回调到c++中方法 我的目录结构 假设我的目录名称是DragonBones -Cocosdx目录 -DragonBones  -c代码 -c代码头 -tools  db_DragonBones.ini genbindings.

cocos2dx lua 绑定之二:手动绑定自定义类中的函数

cococs2dx 3.13.1 + vs2013 + win10 1.首先按照<cocos2dx lua 绑定之一:自动绑定自定义类>绑定Student类 2.在Student类中增加一个用于测试手动绑定的函数manual_call ①Student.h中增加函数 //手动绑定调用函数 void manual_call(); ②Student.cpp中增加函数实现 //和自动绑定相比,只增加了这个函数 void Student::manual_call() { std::cout <&

Cocos2d-x v3.3 lua绑定c++类方法总结

网上有很多cocos2d-x lua绑定c++类的接口教程,这篇文章也是总结他们的经验. 其中重点参考了 http://cn.cocos2d-x.org/tutorial/show?id=1295, 整个过程步骤很详细,会比较傻瓜式,希望对新手读者入门有用. 教程基本环境: 1.使用引擎是v3.3 beta版本 2.开发环境:OSX Yosemite 3. Cocos code IDE 4. Xcode 6 1.在Mac上用Cocos code IDE 写lua还是比较便利的,我们用coco c

Cocos2d-x3.0 lua绑定C++类

这里记录下我实现Lua绑定的全过程. 原文地址:http://blog.csdn.net/qqmcy/article/details/26099859 准备工作: 1.创一个一个Lua的2dx工程.(这个网上已经有好多了) 2.创一个C++类. TestScene.h  这个只是一个简单的场景 // // TestScene.h // uitestLua // // Created by 杜甲 on 14-5-17. // // #ifndef __uitestLua__TestScene__

lua标签解析器

lua 标签解析器 概述 一个类xml标签解析函数,将标签解析成Lua中的表结构它可以用来解析简单xml结构,可以作为RichLabel控件的字符串解析组件(其实它现在就是这么用的;-)) 原理 使用lua的模式匹配, 使用了模式串%b<>%b用来匹配对称的字符.常写为 %bxy,x和y是任意两个不同的字符. x作为匹配的开始,y作为匹配的结束.比如,%b<> 匹配以 < 开始,以 > 结束的字符串 要解析的字符串 hello world <div>hell

cocos2dx v3.x lua绑定分析

打算新项目转到cocos2dx v3上了,下载代码浏览过后发现改动真是非常大,结构性调整很多. 比如tolua绑定这一块,就几乎全翻新了. 胶水代码的生成,改成了全自动式的,通过clang来分析c++代码,可以准确的知道每一个类.函数.参数的信息,再也不用手动写pkg文件了. 运行期对象管理这块,似乎也有了不少改动,至少我原来的一些扩展代码运行不了了,还没来得及细看,待看完再一一录下. 先记录一下目前已看清楚的[类名表.类元表.对象实例]之间的关系: 1.类元表:最核心的表,在lua代码里是不可

【转】如何做dragonbones的lua绑定(VisualStudio)

原文:<如何做dragonbones的lua绑定(VisualStudio)>(不完善和错误的地方我已做红字修改) 最近好多同学在QQ群里问怎么在lua项目中使用DB(DrgonBones,龙骨),为了帮助更多的人,同时也好让更多的人跟容易使用DB,这里详细记录coco2dx-3.2版本对应DB的lua绑定. 首先要说明下,本文章对应的cocos2dx-3.2版本,其他cocos2dx-3.x版本跟3.2版本类似.这里假设自己使用cocos命令行创建的lua项目,而且没有修改过目录结构,如果修

【转】如何做dragonbones的lua绑定(Android)

这篇写dragonbones的lua绑定之Android部分,不知道怎么在VS(Visual Studio)中绑定的话请看如何在lua项目中使用dragonbones.有了上篇的基础,这次再做Android就比较简单了.注意:ndk9b不能编译通过,我这里使用的是ndk9d,其他版面没有测试. 修改 Application.mk 文件路径:MyLuaGame/frameworks/runtime-src/proj.android/jni/Application.mk 添加预定义宏 APP_CPP

如何做dragonbones的lua绑定(mac)

部分文件需要如何做dragonbones的lua绑定(VisualStudio) 支持 a. 将dragonbones(cocos2d_libs), lua_dragonbones_auto.cpp,lua_dragonbones_auto.hpp(cocos2d_lua_bindings/auto)添加到工程 b.  cocos2d_libs/project/Build Settings/Search Paths/User Header Search Paths增加 $(SRCROOT)/..