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方法的流程完成。
cocos2d-x lua绑定解析的更多相关文章
- 使用cocos2d脚本生成lua绑定
这几天要老大要求把DragonBones移到cocos2dx 3.0 里边,并且绑定lua使用接口.因为刚学lua,使用的引擎也刚从2.2改为3.0,各种不熟悉,折腾了好几天才弄完,有空了总结一下 这 ...
- cocos2dx的lua绑定
一.cocos2dx对tolua++绑定的修正 A.c对lua回调函数的引用 在使用cocos2dx编写游戏时,我们经常会设置一些回调函数(时钟.菜单选择等).如果采用脚本方式编写游戏的话,这些回调函 ...
- cocos2dx lua 绑定之二:手动绑定自定义类中的函数
cococs2dx 3.13.1 + vs2013 + win10 1.首先按照<cocos2dx lua 绑定之一:自动绑定自定义类>绑定Student类 2.在Student类中增加一 ...
- Cocos2d-x v3.3 lua绑定c++类方法总结
网上有很多cocos2d-x lua绑定c++类的接口教程,这篇文章也是总结他们的经验. 其中重点参考了 http://cn.cocos2d-x.org/tutorial/show?id=1295, ...
- lua标签解析器
lua 标签解析器 概述 一个类xml标签解析函数,将标签解析成Lua中的表结构它可以用来解析简单xml结构,可以作为RichLabel控件的字符串解析组件(其实它现在就是这么用的;-)) 原理 使用 ...
- ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)
前面文章介绍了ASP.NET MVC中的模型绑定和验证功能,本着ASP.NET MVC没有魔法的精神,本章内容将从代码的角度对ASP.NET MVC如何完成模型的绑定和验证进行分析,已了解其原理. 本 ...
- ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(下篇)
上一篇<ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)>文章介绍了ASP.NET MVC模型绑定的相关组件和概念,本章将介绍Controller在执行时是如何通过这 ...
- cocos2dx lua 绑定之一:自动绑定自定义类中的函数
cococs2dx 3.13.1 + vs2013 + win10 1.首先定义C++类Student 在cocos2d-x\cocos文件夹下新建一个user_define的文件夹放置两个文件. 注 ...
- quick-cocos2d-x 创建自定义lua绑定c++类
内容主要参考 “在quick-cocos2d-x中添加自定义的类给lua使用” ( http://www.codeo4.cn/archives/746) 1. quick-coco2d-x 使用 to ...
随机推荐
- 如何把自己打造成技术圈的papi酱
最近半年,一个叫papi酱的平胸女子连续在微博.朋友圈.创业圈刷屏,当之无愧成了中文互联网的第一大网红.呃,你以为我会巴拉巴拉说一堆网工创业的事?NO,今天想借papi酱的话题跟大家一起聊聊程序员如何 ...
- 一个编程小白,如何入门APP软件开发领域?
近些年,互联网创业火得不得了!一时间,满世界都在招做App软件开发的专业人员.从大众角度来看,学编程,写代码,是一件非常困难的事情.但是,App开发人员的工资那么诱人,让很多小白也跃跃欲试想学一下.那 ...
- centos 下 安装zookpeer
tar xvf zookeeper-3.4.6.tar.gz cd /usr/local/zookpeer/ mkdir /var/zookpeer mkdir /var/zookpeer/data ...
- DuiLib学习bug整理——某些png不能显示
今天下午遇到用ps导出的png显示不出来的情况.而从其他来源的png有的可以显示.到群里问了下也有人遇到过,但是都没想明白具体原因.后来经人指点说png保存时存在深度位不同.最后经过测试 8位深度.3 ...
- Linux系统巡检常用命令
# uname -a # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue # 查看操作系统版本 # cat /proc/cpuinfo # 查看CPU信息 # hostn ...
- IPC
IPC,全名Inter Process Communication即进程间通讯,在同一台机器上的两个进程就用IPC,不能跨物理机器。IPC包括共享内存、队列、信号量等几种方式,由于IPC通讯效率之高, ...
- 分列:将excel单元格的内容拆分为两列
提要:处理excel数据时有时需要把单元格的内容拆分为两列,可能方便外部软件的链接,可能使数据显示更明晰等等,有人说直接剪切加粘贴不就可以了吗,但是有时数据过多,这样处理很不效率,网上搜索的方法说插入 ...
- 十四、Java基础---------String、StringBuffer、StringBuilder基本应用
在前面的博客中曾提及Java的数据类型分为基本数据类型,和引用数据类型,而String便是最常见的应用数据类型,本文将着重介绍这一引用数据类型的用法. String 字符串 String类是对 ...
- [Effective JavaScript 笔记]第7章:并发--个人总结
前言 这一章的内容学到了事件队列和异步的API.js只是运行在其他应用程序的脚本语言.js即依赖于应用程序,也独立与应用程序.可以使它可以在多平台,多种环境上运行.ECMAScript标准中没有关于并 ...
- 关于input内容监听(change)
js的话利用input的onchange事件 而jquery的话利用change()函数,代码如下: <!DOCTYPE html> <html> <head> & ...