从零到一,Cocos2dx-3.x,Lua调用自定义C++方法

5/18/2021 Cocos2dxLua

学习工作项目中Lua和C++如何交互,从新建项目开始

# 一、环境搭建

# 一定要根据Cocos官方文档 (opens new window)中环境要求进行软件版本安装,避免出现各种环境导致的问题

本篇文章基于Cocos2dx-3.17版本:

  • Python版本为2.7+(32位[1]
  • NDK r16+
  • Visual Studio 2015

安装完后,注意检查环境变量是否正确

# 二、项目创建

# 2.1 命令行新建项目

cocos new LuaProjTest -p com.zonst.test -l lua
1

# 2.2 打开项目解决方案,把LuaProjTest设为启动项,并开始调试

  • 初次构建需要等一段时间,如果环境没错,一般不会出现其他问题
  • 如果出现v140v142等版本等问题,可以右键“解决方案”->“重定解决方案目标”
  • 如出现“无法打开文件xxx.lib"问题,大概率是软件环境不匹配
  • 其他具体问题具体分析

1-1.png

# 2.3 在Classes下新建需要增加的类

创建完成后开始调试,看有无报错(具体LuaEngine使用,请查看文末参考资料2-1.png 2-2.png

# 三、使用genbindings脚本生成桥接文件

# 3.1 创建ini文件

进入项目引擎如下目录,复制一份已有的ini文件,并更名为 CUtils.ini 3-1-1.png

打开此文件,需要修改的地方主要在高亮行:

 


 



 

 


















 



 

























 




[CUtils]
# the prefix to be added to the generated functions. You might or might not use this in your own
# templates
prefix = CUtils

# create a target namespace (in javascript, this would create some code like the equiv. to `ns = ns || {}`)
# all classes will be embedded in that namespace
target_namespace = cc
# 此处是宏定义判断,若不需要,可以去除
macro_judgement  = #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN

android_headers = 

android_flags = -target armv7-none-linux-androideabi -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -DANDROID -D__ANDROID_API__=14 -gcc-toolchain %(gcc_toolchain_dir)s --sysroot=%(androidndkdir)s/platforms/android-14/arch-arm  -idirafter %(androidndkdir)s/sources/android/support/include -idirafter %(androidndkdir)s/sysroot/usr/include -idirafter %(androidndkdir)s/sysroot/usr/include/arm-linux-androideabi -idirafter %(clangllvmdir)s/lib64/clang/5.0/include -I%(androidndkdir)s/sources/cxx-stl/llvm-libc++/include

clang_headers = 
clang_flags = -nostdinc -x c++ -std=c++11 -fsigned-char -U__SSE__

cocos_headers = -I%(cocosdir)s -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android -I%(cocosdir)s/external

cocos_flags = -DANDROID

cxxgenerator_headers = 

# extra arguments for clang
extra_arguments = %(android_headers)s %(clang_headers)s %(cxxgenerator_headers)s %(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s %(extra_flags)s 

# what headers to parse
headers = F:/SamerWorld/LuaProjTest/frameworks/runtime-src/Classes/CUtils.h

# what classes to produce code for. You can use regular expressions here. When testing the regular
# expression, it will be enclosed in "^$", like this: "^Menu*$".
classes = CUtils

# what should we skip? in the format ClassName::[function function]
# ClassName is a regular expression, but will be used like this: "^ClassName$" functions are also
# regular expressions, they will not be surrounded by "^$". If you want to skip a whole class, just
# add a single "*" as functions. See bellow for several examples. A special class name is "*", which
# will apply to all class names. This is a convenience wildcard to be able to skip similar named
# functions from all classes.

skip = AudioEngine::[setFinishCallback]

rename_functions =

rename_classes =

# for all class names, should we remove something when registering in the target VM?
remove_prefix = 

# classes for which there will be no "parent" lookup
classes_have_no_parents = AudioEngine AudioProfile

# base classes which will be skipped when their sub-classes found them.
base_classes_to_skip =

# classes that create no constructor
# Set is special and we will use a hand-written constructor
abstract_classes =

# Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'.
script_control_cpp = no
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

# 3.2 修改genbindings.py脚本

3-2.png

# 3.3 执行genbindings.py脚本&可能出现的报错解决方法

建议打开命令行窗口执行此脚本,方便看到报错信息

# 3.3.1 缺少yaml

报错"ImportError: No module named yaml",这是因为未安装yaml模块,下载安装yaml模块即可: http://pyyaml.org/download/pyyaml/PyYAML-3.10.win32-py2.7.exe (opens new window)

# 3.3.2 未安装Cheetah

安装yaml后再运行genbindings.py,报错ImportError: No module named Cheetah.Template,原因是缺少了Cheetah库,下载安装即可 http://github.com/cheetahtemplate/cheetah/zipball/v2.4.2 (opens new window)

  • 将下载完的zip文件解压到任意目录,例如C:\Python27\Lib\cheetahtemplate-cheetah-7b1c2ad\
  • 命令行依次执行以下命令
C:
cd \Python27\Lib\cheetahtemplate-cheetah-7b1c2ad>
python setup.py build
python setup.py install
1
2
3
4

# 3.3.3 Python版本不符

报错"LibclangError:[Error 193]%1不是有效的Win32.To provide a Config.set_library_path() or Config." 按照前面两步安装的yamlCheetah库都是win32版本的,出现这个错误是因为python不是win32版本,全部都用win32版本即可

# 3.4 项目导入桥接文件

# 3.4.1 如果上述步骤都成功了,在frameworks\cocos2d-x\cocos\scripting\lua-bindings\auto中会找到生成的C++的桥接文件,lua_CUtils_auto.cpplua_CUtils_auto.hpp

3-4-1.png

# 3.4.2 项目工程导入桥接文件

3-4-2.png

# 3.4.3 修改桥接文件

  • 引入自定义类的头文件 3-4-3-1.png
  • 如果自定义类中的方法传入了lua回调函数,比如此自定义类的executeWithCb方法,需要修改桥接文件的转换代码(工具Bug) 3-4-3-2.png

# 四、lua脚本调用示例

4-1-1.png 4-1-2.png

# 五、参考资料


# 个人博客:远近相安 (opens new window)

上次更新: 09/02/2021 10:54:32