cocos2d-js由于采用js语言,使得做一些native的功能比较受限,例如文件和目录操作、socket操作等。逼不得已,这时我们就不得不做jsbinding了。。
官方提供的jsbinding方法还是很人性化的,但是网上根本没有找到合适的资料,我就自己先写一篇吧。
用cocos new命令创建工程之后,在 "工程目录/tools/bindings-generator" 目录下有一个generator.py脚本,test目录下有官方示例,这些都是我们需要的。
步骤开始:
1、安装python2.7。然后安装PyYAML和Cheetah,不同平台安装方法可能有区别,Mac下直接到PyYAML和Cheetah的解压目录下执行sudo ./setup.py就可以。
2、把 "工程目录/tools/bindings-generator/test" 下面的test.ini、test.sh、userconf.ini.sample这三个文件拷贝一份到自己能找到的地方,并把userconf.ini.sample重命名为userconf.ini。
3、修改userconf.ini,指定androidndkdir、clangllvmdir、cxxgeneratordir的路径。
4、修改test.ini,需要修改的有:引用的头文件的路径、绑定的类名、命名空间。下面是我的配置,使用我的配置,只需要修改前7行就可以。后面的可以不管。
1 [testandroid] 2 name = red_bindings 3 prefix = red_bindings_auto 4 classes = RedSprite RedClass 5 cocosdir = /Users/staff/Documents/Red_Test/jsb_test/frameworks/js-bindings/cocos2d-x 6 customdir = /Users/staff/Documents/Red_Test/jsb_test/frameworks/runtime-src/Classes 7 headers = %(customdir)s/RedBindings.h 8 target_namespace = red 9 10 android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/include 11 android_flags = -D_SIZE_T_DEFINED_ 12 13 clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include 14 clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__ 15 16 cocos_headers = -I%(cocosdir)s -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos/platform/android 17 18 cocos_flags = -DANDROID 19 20 extra_arguments = %(android_headers)s %(clang_headers)s %(customdir)s %(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s %(extra_flags)s 21 22 remove_prefix = 23 skip = 24 base_objects = 25 abstract_classes = 26 classes_have_type_info = no 27 rename = 28 rename_functions = 29 rename_classes = 30 # classes for which there will be no "parent" lookup 31 classes_have_no_parents = 32 33 # base classes which will be skipped when their sub-classes found them. 34 base_classes_to_skip = 35 36 # 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'. 37 script_control_cpp = yes
5、修改test.sh,第39行修改CXX_GENERATOR_ROOT,指向 "工程目录/tools/bindings-generator" 就可以。
6、修改最后一行,指定test.ini的路径和生成代码的路径。下面是我的配置:
1 #!/bin/bash 2 # 3 # Usage: 4 # export NDK_ROOT=/path/to/NDK-r9b 5 # ./test.sh 6 7 # exit this script if any commmand fails 8 set -e 9 10 # read user.cfg if it exists and is readable 11 12 _CFG_FILE=$(dirname "$0")"/user.cfg" 13 if [ -f "$_CFG_FILE" ]; 14 then 15 if [ ! -r "$_CFG_FILE" ]; then 16 echo "Fatal Error: $_CFG_FILE exists but is unreadable" 17 exit 1 18 fi 19 fi 20 21 # paths 22 23 if [ -z "${NDK_ROOT+aaa}" ]; then 24 # ... if NDK_ROOT is not set, use "$HOME/bin/android-ndk" 25 NDK_ROOT="$HOME/bin/android-ndk" 26 fi 27 28 if [ -z "${PYTHON_BIN+aaa}" ]; then 29 # ... if PYTHON_BIN is not set, use "/usr/bin/python2.7" 30 PYTHON_BIN="/usr/bin/python2.7" 31 fi 32 33 # find current dir 34 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 35 36 # paths with defaults hardcoded to relative paths 37 38 if [ -z "${CXX_GENERATOR_ROOT+aaa}" ]; then 39 CXX_GENERATOR_ROOT="/Users/staff/Documents/Red_Test/jsb_test/tools/bindings-generator" 40 fi 41 42 43 echo "Paths" 44 echo " NDK_ROOT: $NDK_ROOT" 45 echo " PYTHON_BIN: $PYTHON_BIN" 46 echo " CXX_GENERATOR_ROOT: $CXX_GENERATOR_ROOT" 47 echo " TO_JS_ROOT: $TO_JS_ROOT" 48 49 # check NDK version, must be r9b 50 # if ! grep -q r9b $NDK_ROOT/RELEASE.TXT 51 # then 52 # echo " Fatal Error: NDK r9b must be required!" 53 # exit 1 54 # fi 55 56 # check clang include path 57 OS_NAME=$('uname') 58 NDK_LLVM_ROOT=$NDK_ROOT/toolchains/llvm-3.3/prebuilt 59 if [ ! -d "$DIRECTORY" ]; then 60 NDK_LLVM_ROOT=$NDK_ROOT/toolchains/llvm-3.4/prebuilt 61 fi 62 case "$OS_NAME" in 63 Darwin | darwin) 64 echo "in darwin" 65 if [ -d "$NDK_LLVM_ROOT/darwin-x86_64" ]; then 66 NDK_LLVM_ROOT=$NDK_LLVM_ROOT/darwin-x86_64 67 elif [ -d "$NDK_LLVM_ROOT/darwin-x86" ]; then 68 NDK_LLVM_ROOT=$NDK_LLVM_ROOT/darwin-x86 69 else 70 echo $NDK_LLVM_ROOT 71 echo " Fatal Error: $NDK_LLVM_ROOT doesn't contains prebuilt llvm 3.3 or 3.4" 72 exit 1 73 fi 74 ;; 75 Linux | linux) 76 echo "in linux" 77 if [ -d "$NDK_LLVM_ROOT/linux-x86_64" ]; then 78 NDK_LLVM_ROOT=$NDK_LLVM_ROOT/linux-x86_64 79 elif [ -d "$NDK_LLVM_ROOT/linux-x86" ]; then 80 NDK_LLVM_ROOT=$NDK_LLVM_ROOT/linux-x86 81 else 82 echo " Fatal Error: $NDK_LLVM_ROOT doesn't contains prebuilt llvm 3.3 or 3.4" 83 exit 1 84 fi 85 ;; 86 *) 87 echo " Fatal Error: Please run this script in linux or mac osx." 88 exit 1 89 ;; 90 esac 91 92 93 # write userconf.ini 94 95 _CONF_INI_FILE="$PWD/userconf.ini" 96 if [ -f "$_CONF_INI_FILE" ] 97 then 98 rm "$_CONF_INI_FILE" 99 fi 100 101 _CONTENTS="" 102 _CONTENTS+="[DEFAULT]"' ' 103 _CONTENTS+="androidndkdir=$NDK_ROOT"' ' 104 _CONTENTS+="clangllvmdir=$NDK_LLVM_ROOT"' ' 105 _CONTENTS+="cxxgeneratordir=$CXX_GENERATOR_ROOT"' ' 106 _CONTENTS+="extra_flags="' ' 107 108 echo 109 echo "generating userconf.ini..." 110 echo --- 111 echo -e "$_CONTENTS" 112 echo -e "$_CONTENTS" > "$_CONF_INI_FILE" 113 echo --- 114 115 # Generate bindings for cocos2dx 116 echo "Generating bindings for cocos2dx..." 117 set -x 118 119 LD_LIBRARY_PATH=${CXX_GENERATOR_ROOT}/libclang $PYTHON_BIN ${CXX_GENERATOR_ROOT}/generator.py /Users/staff/Documents/Red_Test/jsb_test/frameworks/bindingconf/red_bindings.ini -t spidermonkey -s testandroid -o ./simple_test_bindings
7、执行刚才的sh文件应该就会在指定的目录生成绑定代码了。把生成的cpp和hpp文件复制到 "工程目录/frameworks/runtime-src/Classes" 中,修改AppDelegate.cpp,include刚生成的hpp,在applicationDidFinishLaunching函数中添加"sc->addRegisterCallback(register_all_red_bindings_auto);"(参数是注册绑定的函数指针,一般都是已"register_all"开头)。
8、编译runtime就可以了,实测在Mac、android、ios都可以。