在公司3个月的一些积累

本文详细介绍了Lua与C++的交互过程,包括Lua的基本概念、Lua与C++的绑定方法、Cocos2d-x环境下Lua调用C++的具体步骤及场景切换函数等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文不会涉及到任何公司项目等相关的内容,完全是个人平时的积累。

lua相关

1.pairs 和 ipairs 的区别:

  • pairs可以遍历表中的所有元素,可以返回Nil
  • ipairs则不可以返回nil,只能返回0,遇到nil则退出,他只能遍历到表中出现的第一个不是整数的key

2.lua深拷贝table

lua 除了简单类型分配内存外,table只是传递引用,所以不能用简单的”=”来copy两个表,并试图修改一个表中的值。

下面方法实现table copy: –lua table 拷贝
function table_copy_table(ori_tab)
if (type(ori_tab) ~= "table") then
return nil
end
local new_tab = {}
for i,v in pairs(ori_tab) do
local vtyp = type(v)
if (vtyp == "table") then
new_tab[i] = table_copy_table(v)
elseif (vtyp == "thread") then
new_tab[i] = v
elseif (vtyp == "userdata") then
new_tab[i] = v
else
new_tab[i] = v
end
end
return new_tab
end

3.”_G”lua的全局表

4.关于lua绑定C++代码

自从Cocos2d-x 3.0,我们使用 bindings-generator 自动生成 c++ lua 绑定。
bindings-generator 是基于 tolua++,你可以配置 tools/tolua目录下的ini文件,
然后运行genbindings.py脚本生成绑定代码。通过使用这种方法,大大降低了记录的pkg文件的配置工作。

http://segmentfault.com/a/1190000000631630
关于cocos2d-x下Lua调用C++的文档看了不少,但没有一篇真正把这事给讲明白了,我自己也是个初学者,摸索了半天,总结如下:
cocos2d-x下Lua调用C++这事之所以看起来这么复杂、网上所有的文档都没讲清楚,是因为存在5个层面的知识点:
1、在纯C环境下,把C函数注册进Lua环境,理解Lua和C之间可以互相调用的本质
2、在cocos2d-x项目里,把纯C函数注册进Lua环境,理解cocos2d-x是怎样创建Lua环境的、以及怎样得到这个环境并继续自定义它
3、了解为什么要使用toLua++来注册C++类
4、在纯C++环境下,使用toLua++来把一个C++类注册进Lua环境,理解toLua++的用法
5、在cocos2d-x项目里,使用cocos2d-x注册自身的方式把自定义的C++类注册进Lua环境,
理解cocos2d-x是怎样通过bindings-generator脚本来封装toLua++的用法来节省工作量的
只有理解了前4层,在最后使用bindings-generator脚本的时候心里才会清清楚楚。而网上的文档,要么是只解释了第1层,
要么是只填鸭式地告诉你第5层怎么用bindings-generator脚本,不仅中间重要的知识点一概不提,示例代码往往也写的不够简洁,
这让我这种看见C++就眼晕的人理解起来大为头疼(不是我不会C++,而是我非常不接受C++的设计哲学,能避就避)。
所以接下来的讲解我会对每一层知识点逐一讲解,示例代码也不求完整严谨,而是尽量用最简洁的方式把程序的关键点说明白。

5.如何实现?

总结一下cocos2d-x 3.8将C++类注册进lua环境

前提工具:
cocos2d-x 3.8
NDK_ROOT 必须为android-ndk-r9b(解压缩引擎,运行setup.py时设置ndk_root)
python插件:Cheetah、PyYAML(3.10以上版本、有32、64可选,但现在必选32,这个设置在下面有说明)

下面提到的所有路径都是基于新创建工程的路径,而不是引擎的路径。注意大小写!!!!
创建新工程的命令 : cocos.py new MyGame -p com.test.mygame -l cpp -d C:\test

1.自定义C++类,按照cocos2d-x的方法继承Ref类。包括.h和.cpp文件
首先是自定义的C++类。我习惯将文件保存在frameworks/runtime-src/Classes/目录下:
#include “cocos2d.h”
using namespace cocos2d;
class MyClass : public Ref{
public:
MyClass() {};
~MyClass() {};
bool init() { return true; };
CREATE_FUNC(MyClass);
int foo(int i);
};

#include “MyClass.h”
int MyClass::foo(int i){
return i + 100;
}

2.编写.ini文件,在tools/tolua目录,只需要修改部分的东西就可以使用
[MyClass]
prefix = MyClass
target_namespace = my
headers = %(cocosdir)s/../runtime-src/Classes/MyClass.h
classes = MyClass
更详细的说明:
headers 填入你所编写的代码的头文件
classes 填入要生成的类,支持多个类,支持正则表达式,如classes = A,^A,^A skipluaskip=Sprite::[getQuadgetBlendFuncsetPosition setBlendFunc]
rename_functions 重新命名暴露到lua中函数名(一般以C++编写函数名暴露到lua),如
rename_functions = SpriteFrameCache::[addSpriteFramesWithFile=addSpriteFrames getSpriteFrameByName=getSpriteFrame],
等号前是原函数名,等号后是lua中的新函数名
rename_classes重命名类,如 rename_classes = SimpleAudioEngine::AudioEngine。前面是原名,后面是lua新名。这个好像没效果,生成后还是那个名字
classes_have_no_parents 指定一些没有父类的类
base_classes_to_skip 指定一些需要跳过的基类
abstract_classes 指定一些抽象类或者没有构造函数的类,以手动方式编写注册到lua函数
自动生成的代码会自动过滤掉C++中的protect、private属性、重载父类的函数、带省略号参数的函数(如Menu::create(MenuItem* item, …) )

3.运行genbindings.py(一定要cd 进入到cocos2d-x/tools/tolua目录,不能使用完全路径,否则不成功)
编写或者修改genbindings.py要注意点的:

在129行左右,设置cmd_args参数时,第一是ini文件名,最后一个是要生成的文件名,重点是第二个,这个参数是生成器在ini文件里面
查找对应的块(即ini文件中中括号对应的文字,如[cocos2dx],一般是第一行),形如
cmd_args = {‘custom.ini’ : (‘custom’, ‘lua_custom_auto’) }就是查找custom.ini中的[custom]段配置,
最后生成名为lua_custom_auto的文件,如果第二个参数没对应上,出现Section not found in config file的错误

(在Mac系统上可能会遇到缺少yaml、Cheetah包的问题,安装这些Python包很简单,先sudo easy_install pip,把pip装好,
然后用pip各种pip search、sudo pip install就可以了)

运行的时间比较长,在最后会提示
Generating lua bindings succeeds.
表示成功了,我们就能在cocos/scripting/lua-bindings/auto/找到lua_myClass_auto.cpp和对应的hpp文件了

4.如何调用?

在tools/simulator/framework/runtime-src/Classes/AppDelegate.cpp文件修改如下内容
添加 #include “lua_myClass_auto.hpp”
register_all_myClass(stack->getLuaState());
将lua_myClass_auto.hpp 和cpp文件添加到工程目录中

===编译成功,连接时候出错了。。。
Undefined symbols for architecture x86_64:
“register_all_myClass(lua_State*)”, referenced from:
AppDelegate::applicationDidFinishLaunching() in AppDelegate.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

不知道改了什么,现在又变成myClass.h找不到了,重新配置编译时工程引用的头文件位置
参考文章:
http://segmentfault.com/a/1190000000631630
http://www.bubuko.com/infodetail-424341.html

6.lua与C++通信的过程

7 -> -> ->
C++ | lua堆栈 | lua | lua全局表
<- <- <-

1.C++想要获取lua的myname字符串的值,所以把myname放到lua堆栈的栈顶
2.lua从栈顶获取myName,此时栈顶变为空
3.lua拿着myName去lua全局表查找myName对应的字符串
4.全局表返回一个字符串”mmmmm“
5.lua把取得的字符串放到栈顶
6.C++获取到栈顶的名字”mmmmm“

7.——3.x中场景切换的函数:

场景的切换是通过导演类来实现的
·runWithScene(scene) 只在启动第一个场景的时候调用,如果已经有一个场景运行则不可调用这个函数
·replaceScene(scene) 切换场景,旧的场景会被释放掉
·pushScene(scene) 切换场景,当前场景会被挂起放入场景堆栈中,然后在切换到下一个场景
·popScene(scene) 与pushScene配合使用,可以回到上一个场景
·popToRootScene() 与pushScene 配合使用,可以回到根场景
例:
cc.Director:getInstance():replaceScene(scene)
cc.Director:getInstance():pushScene(scene)
Director:getInstance()->popScene(); // 回到上一个场景

Scene以及所有节点(Node)的生命周期:
·enter
·enterTransitionFinish 进入场景并过度动画结束时触发
·exit 退出
·exitTransitionDidStart 退出场景并且开始过度动画时触发
·cleanup 场景对象被清除

lua中的require机制 http://blog.chinaunix.net/uid-552961-id-2736410.html

大型手游登录流程:
http://www.it165.net/pro/html/201509/53435.html

touch事件一定要在touchBegan中返回true,否则后面的事件会监听不到

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值