標籤:android des http java os io 檔案 for
Cocos2d-x 3.1 Lua Binding
參考:http://www.cocos2d-x.org/docs/manual/code-ide/binding-custom-class-to-lua/en
添加需要綁定的C++類
在xcode中,把my檔案夾拖到cocos2d_libs.xcodeproj中
HNLuaTest.h
//// HNLuaTest.h// cocos2d_libs//// Created by Eleven Chen on 14-8-5.////#ifndef __cocos2d_libs__HNLuaTest__#define __cocos2d_libs__HNLuaTest__#include "cocos2d.h"#include <string>class Test : public cocos2d::Ref{public: static std::string helloMsg(); static Test* create(); bool init(); static cocos2d::Vec2 left();};#endif /* defined(__cocos2d_libs__HNLuaTest__) */ HNLuaTest.cpp
//// HNLuaTest.cpp// cocos2d_libs//// Created by Eleven Chen on 14-8-5.////#include "HNLuaTest.h"using namespace cocos2d;std::string Test::helloMsg(){ return "Hello from HNLuaTest::helloMsg()";}Test* Test::create(){ return new Test();}bool Test::init(){ return true;}Vec2 Test::left(){ return Vec2(0, 0);} 編寫ini檔案
進入到tolua目錄:$(PROJECT_ROOT)/frameworks/cocos2d-x/tools/tolua
在之前先看看README檔案,並安裝好環境。
README檔案中提到必須要用android ndk r9b來編譯,因為編譯的時候用到了C++ std 4.7的標頭檔,而r9b包含了4.7,我用的是r9d,只有4.6和4.8。我把*.ini檔案裡面的4.7改成4.8來編譯。
建立一個cocos2dx_custom.ini檔案,然後從其他檔案裡面copy一份代碼過來修改,代碼裡面每一個設定都有詳細的注釋。
clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include # the prefix to be added to the generated functions. You might or might not use this in your own# templatesprefix = cocos2dx_custom# create a target namespace (in javascript, this would create some code like the equiv. to `ns = ns || {}`)# all classes will be embedded in that namespacetarget_namespace = cc# the native namespace in which this module locates, this parameter is used for avoid conflict of the same class name in different modules, as "cocos2d::Label" <-> "cocos2d::ui::Label".cpp_namespace = android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/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/includeandroid_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include clang_flags = -nostdinc -x c++ -std=c++11cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos/platform/androidcocos_flags = -DANDROIDcxxgenerator_headers = # extra arguments for clangextra_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 parseheaders = %(cocosdir)s/cocos/my/HNLuaTest.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 = Test.*# 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 = 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" lookupclasses_have_no_parents = Test# 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 constructorabstract_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 編寫genbindings.py
為了方便,每次綁定時不需要產生cocos2d-x的綁定代碼,建立一個genbindings_custom.py檔案,然後複製genbindings.py的代碼過來,把下面的地方:
cmd_args = {‘cocos2dx.ini‘ : (‘cocos2d-x‘, ‘lua_cocos2dx_auto‘), ‘cocos2dx_extension.ini‘ : (‘cocos2dx_extension‘, ‘lua_cocos2dx_extension_auto‘), ‘cocos2dx_ui.ini‘ : (‘cocos2dx_ui‘, ‘lua_cocos2dx_ui_auto‘), ‘cocos2dx_studio.ini‘ : (‘cocos2dx_studio‘, ‘lua_cocos2dx_studio_auto‘), ‘cocos2dx_spine.ini‘ : (‘cocos2dx_spine‘, ‘lua_cocos2dx_spine_auto‘), ‘cocos2dx_physics.ini‘ : (‘cocos2dx_physics‘, ‘lua_cocos2dx_physics_auto‘), ‘custom.ini‘: (‘custom‘, ‘lua_custom_auto‘), ‘cocos2dx_custom.ini‘ : (‘cocos2dx_custom‘, ‘lua_cocos2dx_custom_auto‘), }
改為
cmd_args = {‘cocos2dx_custom.ini‘ : (‘cocos2dx_custom‘, ‘lua_cocos2dx_custom_auto‘), } 運行genbindings_custom.py
./genbindings_custom.py
產生的程式碼在 cocos/scripting/lua-bindings/auto裡面
mac和ios的整合
- 把產生的hpp和cpp拖到cocos2d_lua_bindings.xcodeproj/auto中
- 在cocos2d_lua_bindings.xcodeproj 的Build Settings中設定標頭檔搜尋,添加
my
Android整合
- 在
my檔案夾中添加Android.mk檔案,如下內容
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := cocos_custom_staticLOCAL_MODULE_FILENAME := libmyLOCAL_SRC_FILES := HNLuaTest.cppLOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)./LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)./LOCAL_CFLAGS += -Wno-psabiLOCAL_EXPORT_CFLAGS += -Wno-psabiLOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_staticinclude $(BUILD_STATIC_LIBRARY)$(call import-module,.)
- 開啟lua-bindings檔案夾的Android.mk檔案,添加以下內容
註冊到Lua
修改AppDelegate.cpp
//register custom function //LuaStack* stack = engine->getLuaStack(); //register_custom_function(stack->getLuaState()); LuaStack *stack = engine->getLuaStack(); auto L = stack->getLuaState(); if (L) { lua_getglobal(L, "_G"); register_all_cocos2dx_custom(L); lua_settop(L, 0); }#if (COCOS2D_DEBUG>0) if (startRuntime()) return true;#endif engine->executeScriptFile(ConfigParser::getInstance()->getEntryFile().c_str()); return true;
這裡不能按照原本代碼注釋的方法那樣做,那樣會出錯。
而且都是tolua_module這個函數裡面的lua_rawget(L,-2);這一行出錯。
原因是:
- auto engine = LuaEngine::getInstance();
- _defaultEngine->init();
- executeScriptFile(“Deprecated.lua”);
- _stack->clean();
- lua_settop(_state, 0);
LuaEngine初始化的時候會運行3個lua檔案,把stack給清空了。
在tolua_module函數中,lua_pushstring(L,name);後,棧只有一個元素,所以lua_rawget(L,-2);就會出錯。
只需要把_G放到棧中,再運行register_all_cocos2dx_custom(L);,如果模組不在_G中,就添加到_G中,就可以全域訪問了。
cocos code ide build custom runtime
測試
-- test custom local msg = cc.Test:helloMsg() print(msg)
輸出