Cocos2dx-JS綁定C++大致流程

Cococs2dx-JS 版本3.12,環(huán)境:Mac
。這里有兩種情況,為修改引擎底層方法和自定義新的C++類。

首先為了保證genbindings.py 正常運行 你需要下3樣東西 已安裝的請略過

  1. python 2.7.x:目前引擎里面的bindings-generator只支持python2.7.x版本
  2. py-ymal(http://pyyaml.org/wiki/PyYAML):這是python的一個第三方包,下載頁有不同系統(tǒng)的安裝方式,可以參考generator.py會調用到這個包。
  3. cheetah(http://www.cheetahtemplate.org/):這也是python的一個第三方包,一個模板,generator.py會調用到這個包.

安裝目錄執(zhí)行 python setup.py install 進行安裝.

修改引擎底層方法

這個比較簡單,這里做的是給UIImageView添加了一個public方法。然后在js中用一個UIImageView對象去調用這個方法。
首先在UIImageView.cpp中添加如下方法:

void ImageView::getImageDes()
{
    CCLOG("this is getImageDes!!");
}

然后到工程/frameworks/cocos2d-x/tools/tojs目錄下執(zhí)行python腳本genbindings.py。(可以對這個腳本修改,然后只是重新綁定UIImageView相關的文件)。然后就可以在/frameworks/cocos2d-x/cocos/scripting/js-bindings/auto目錄下的jsb_cocos2dx_ui_auto.cpp文件中看到相應的綁定內容。如下:

bool js_cocos2dx_ui_ImageView_getImageDes(JSContext *cx, uint32_t argc, jsval *vp)
{
    JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
    JS::RootedObject obj(cx, args.thisv().toObjectOrNull());
    js_proxy_t *proxy = jsb_get_js_proxy(obj);
    cocos2d::ui::ImageView* cobj = (cocos2d::ui::ImageView *)(proxy ? proxy->ptr : NULL);
    JSB_PRECONDITION2( cobj, cx, false, "js_cocos2dx_ui_ImageView_getImageDes : Invalid Native Object");
    if (argc == 0) {
        cobj->getImageDes();
        args.rval().setUndefined();
        return true;
    }

    JS_ReportError(cx, "js_cocos2dx_ui_ImageView_getImageDes : wrong number of arguments: %d, was expecting %d", argc, 0);
    return false;
}

然后在js腳本中就可以調用getImageDes方法了,如下:

this._image.getImageDes();

控制臺就可以看到打印。這種方式還是比較簡單的綁定。

添加自定義的C++類

這里我創(chuàng)建了一個簡單的C++類,CustomClass:
CustomClass.h

#ifndef CUSTOMCLASS
#define CUSTOMCLASS
#include "cocos2d.h"
namespace cocos2d {
  class CustomClass : public cocos2d::Ref
  {
    public:
      CustomClass();
      ~CustomClass();
      bool init();
      std::string helloMsg();
      CREATE_FUNC(CustomClass);
  };
} //namespace cocos2d
#endif // CUSTOMCLASS

CustomClass.cpp

#include "CustomClass.h"
USING_NS_CC;
CustomClass::CustomClass(){
}
CustomClass::~CustomClass(){
}
bool CustomClass::init(){
  return true;
}
std::string CustomClass::helloMsg(){
  return "this is CustomClass Msg!";
}

然后把這個類放在游戲工程目錄/frameworks/cocos2d-x/cocos/my/下。


file.png

然后把my文件夾導入到cocos2d_libs工程中,


structure.png

并為cocos2d_libs工程的 User Header Searcher Paths,添加目錄,指定到my目錄下,$(SRCROOT)/../../../../cocos/my

add_header_search_path.png

同時,我也為游戲工程添加了這個目錄(這個覺得是沒有必要的)。
然后在tojs文件夾下添加cocos2dx_custom.ini文件。這個可以復制一份,然后修改相應的位置,主要是
headers = %(cocosdir)s/cocos/my/CustomClass.h 這個是頭文件的路徑,然后是
classes = CustomClass.* 這個是要包含進來的類
classes_need_extend = CustomClass 需要在js里面派生的類

然后修改 genbindings.py這個文件,151行的位置,添加剛才的cocos2dx_custom.init文件,如下:

cmd_args = {'cocos2dx.ini': ('cocos2d-x', 'jsb_cocos2dx_auto'),
            'cocos2dx_custom.ini': ('cocos2dx_custom', 'jsb_cocos2dx_custom_auto'),
            }

這是一份完整的cocos2dx_custom.ini:

[cocos2dx_custom]
# the prefix to be added to the generated functions. You might or might not use this in your own
# templates
prefix = 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 namespace
target_namespace = ccext

android_headers = -I%(androidndkdir)s/platforms/android-19/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
android_flags = -D_SIZE_T_DEFINED_ 

clang_headers = -I%(clangllvmdir)s/lib/clang/%(clang_version)s/include 
clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__


cocos_headers = -I%(cocosdir)s -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/base -I%(cocosdir)s/cocos/platform/android -I%(cocosdir)s/extensions -I%(cocosdir)s/external -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos/network -I%(cocosdir)s/cocos/ui/UIEditBox -I%(cocosdir)s/cocos/ui -I%(cocosdir)s/jsext -I%(cocosdir)s/jsext/system -I%(cocosdir)s/jsext/alipay  -I%(cocosdir)s/jsext/video -I%(cocosdir)s/jsext/webview -I%(cocosdir)s/jsext/umeng
#cocos_headers = -I%(cocosdir)s -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android

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 = %(cocosdir)s/cocos/extra/CustomClass.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 = CustomClass.*

#需要在js里面派生的類
#classes_need_extend = CustomClass

# 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" lookup
classes_have_no_parents = 

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

# 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

剩下的就是運行 python genbindings.py,綁定成功之后可以在項目/frameworks/cocos2d-x/cocos/scripting/js-bindings/auto目錄下看到對應的jsb_cocos2dx_custom_auto.hpp和jsb_cocos2dx_custom_auto.cpp,同時在這個目錄下有一個api文件夾,jsb_cocos2dx_custom_api.js也相應的生成了。
然后把這兩個文件導入到cocos2d_js_bindings工程的auto文件夾下。


jsb_binding_structure.png

然后在AppDelegate.cpp文件中注冊,如下:

//jsbinding test
sc->addRegisterCallback(register_all_cocos2dx_custom);

然后我們就可以在js代碼中使用我們的C++類了

var customClass = ccext.CustomClass.create();
var msg = customClass.helloMsg()
cc.log("customClass's msg is========>>>" + msg)

此時可以在控制臺看到打印log。至此,js綁定C++已經完成 。

然后就是 Android 下面的處理。主要是把我們新添加的類,包含到Android.mk中。首先到項目/frameworks/cocos2d-x/cocos/scripting/js-bindings/proj.android/目錄下,找到Android.mk ,然后在 LOCAL_C_INCLUDES下,包含我們的新添加的類的路徑。在 LOCAL_SRC_FILES下包含,我們的cpp文件,如下: ../auto/jsb_cocos2dx_custom_auto.cpp \ 。同時,要保證我們的原始的C++類也包含到mk文件中,保證變異的時候能找到我們的原始C++文件。然后這樣Android下面編譯也沒什么問題了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容