cocos2d-js javascriptbinding实现

cocos2dx新创建项目android部分却少build_native.py 文件需要用cocos 命令行进行编译:

基础配置部分: (for mac)

/cocos2d-x-3.x/tools/cocos2d-console/bin下 (ccoos2dx 3.12)

1.   chmod u+x cocos.py  

2.   ./cocos.py new HelloWorldDemo -p com.coco2dx.org -l cpp -d ~/Desktop  (创建项目)

3.   先要cd进入proj.android目录 cocos compile -p android   (debug 编译)

4.   先要cd进入proj.android目录 cocos compile -p android -m release (release 编译)

5.   下载macport 软件下载:http://www.ccvita.com/434.html(找到对应的操作系统版本)

      官网(https://www.macports.org/install.php)

      - 环境变量设置: 

      修改.bash_profile 文件 添加:

      export PATH=/opt/local/bin:$PATH

      export PATH=/opt/local/sbin:$PATH

      source .bash_profile (修改环境变量)

        

      - 操作指南:

      sudo port -v selfupdate  (mac ports更新)

      port search name (搜索软件)

      sudo port install name (安装软件)

      sudo port uninstall name (卸载软件)

      port outdated (查看软件版本)

      sudo port upgrade outdated (升级软件)


    - mac port 安卓:

    

sudo port -v selfupdate

sudo port install python27 py27-yaml py27-cheetah


6.   下来jsbinding一次你就知道有多坑, js版本必须要把原工程的tools拷贝过来(这里可以直接使用cocos2dx引擎下的tools文件夹即可),否则是不可以 python genbindings.py 无法使用的, 但是lua比较正常;

7.   进入当前生成项目下的tools 中的 tojs文件加,复制一下cocos2dx_experimental_webView.ini进行修改操作,重命名TestJSB.ini;

      - 修改项:

        [TestJSB]

        # the prefix to be added to the generated functions. You might or might not use this in your own

        # templates

        prefix = TestJSB

        

        # 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 = my

        

                    macro_judgement  = #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS) && !defined(CC_TARGET_OS_TVOS)

        

        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

        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/cocos -I%(cocosdir)s/cocos/editor-support -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/../runtime-src/Classes/TestJSB.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 = TestJSB

        

        # 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 =

        

        # 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


8.   添加c++ 原文件与头文件:

      - 文件名称:

        TestJSB.h

        TestJSB.cpp

        

- 代码:    

// TestJSB.h

//  TestJSB.hpp

//  TestCocosJs

//

//  Created by kaitiren on 16/8/4.

//

//


#ifndef TestJSB_hpp

#define TestJSB_hpp


#include <stdio.h>

#include "cocos2d.h"


using namespace cocos2d;




class TestJSB : public cocos2d::Layer

{

public:

    TestJSB();

    ~TestJSB();

    void testprint(void);

    void testString(const char* _str);

    void testInt(int value);

    void testLong(long value);

    void testBool(bool isBoo);

    

    

    CREATE_FUNC(TestJSB);

};


#endif /* TestJSB_h */


///  TestJSB.cpp


//

//  TestJSB.cpp

//  TestCocosJs

//

//  Created by kaitiren on 16/8/4.

//


#include "TestJSB.h"


TestJSB:: TestJSB()

{

    printf("\n TestJSB:: TestJSB() \n");

}



TestJSB:: ~TestJSB()

{

    

}



void TestJSB:: testprint(void)

{

    CCLOG("TestJSB:: testprint(void)");

    printf("\n TestJSB:: testprint(void) \n");

}



void TestJSB:: testString(const char* _str)

{

     printf("\n TestJSB:: testString(_str): %s \n",_str);

}



void TestJSB:: testInt(int value)

{

    printf("\n TestJSB:: testInt: %d \n ",value);

}



void TestJSB:: testLong(long value)

{

     printf("\n TestJSB:: testLong: %ld \n ",value);

}



void TestJSB:: testBool(bool isBoo)

{

    printf("\n TestJSB:: testBool: %d \n",isBoo);

}

/// cpp

 

9.   编译python genbindings.py 文件,查看错误部分,并且修改, 完成后进行添加到xcode工程(注意: 在cocos2d_js_bindings.xcodeproj项目下的auto 文件加进行添加,这里有一个坑是必须要添加到ios项目内,否则识别不到);


坑: 如果cpp文件头文件搜索不到自行添加一下即可;

注意导入头文件部分: #include "../../../../../runtime-src/Classes/TestJSB.h"

修改genbindings.py文件:

 cmd_args = {

                    #'cocos2dx.ini': ('cocos2d-x', 'jsb_cocos2dx_auto'),

                    #'cocos2dx_audioengine.ini': ('cocos2dx_audioengine', 'jsb_cocos2dx_audioengine_auto'),

                    #'cocos2dx_extension.ini': ('cocos2dx_extension', 'jsb_cocos2dx_extension_auto'),

                    #'cocos2dx_builder.ini': ('cocos2dx_builder', 'jsb_cocos2dx_builder_auto'),

                    #'cocos2dx_ui.ini': ('cocos2dx_ui', 'jsb_cocos2dx_ui_auto'),

                    #'cocos2dx_studio.ini': ('cocos2dx_studio', 'jsb_cocos2dx_studio_auto'),

                    #'cocos2dx_spine.ini': ('cocos2dx_spine', 'jsb_cocos2dx_spine_auto'),

                    #'cocos2dx_3d.ini': ('cocos2dx_3d', 'jsb_cocos2dx_3d_auto'),

                    #'cocos2dx_3d_ext.ini': ('cocos2dx_3d_extension', 'jsb_cocos2dx_3d_extension_auto'),

                    #'cocos2dx_experimental_webView.ini': ('cocos2dx_experimental_webView', 'jsb_cocos2dx_experimental_webView_auto'),

                    #'cocos2dx_experimental_video.ini': ('cocos2dx_experimental_video', 'jsb_cocos2dx_experimental_video_auto'),

                    #'cocos2dx_physics3d.ini': ('cocos2dx_physics3d', 'jsb_cocos2dx_physics3d_auto'),

                    'cocos2dx_navmesh.ini': ('cocos2dx_navmesh', 'jsb_cocos2dx_navmesh_auto'),

                    #################################################

                    'TestJSB.ini': ('TestJSB', 'jsb_testjsb_auto'),

                    'JSBindingIOSWXManager.ini': ('JSBindingIOSWXManager', 'jsbinding_ioswxmanager_auto'),#添加部分

                    }



10.   进入当前项目的Classes中的AppDelegate.cpp:

    - 修改代码:

    添加: #include "scripting/js-bindings/auto/jsb_testjsb_auto.hpp"

    注册代码:   sc->addRegisterCallback(register_all_TestJSB); 这里可以从 jsb_testjsb_auto.hpp 中查找;

  完成后进行xcode build操作;

        

11.   进行js代码编辑与测试: (进入 app.js HelloWorldScene)

        - 添加测试代码

var HelloWorldScene = cc.Scene.extend({

    onEnter:function () {

        this._super();

        var layer = new HelloWorldLayer();

        this.addChild(layer);

        ///

        console.log("aaaaaaaassssssss");

        ///

        var testJSB = new my.TestJSB();

        testJSB.testprint();

        testJSB.testString("pppppppppppppppppppppppp");

        testJSB.testInt(123);

        testJSB.testLong(999999999999);

        testJSB.testBool(true);

    }

});

 控制台输出如果正常js 调用 c++ 部分结束;


12.   解决c++ 调用 js 部分: (进入jsb_testjsb_auto.cpp文件夹)

c++ 模块:

bool js_TestJSB_TestJSB_testString(JSContext *cx, uint32_t argc, jsval *vp)

{

    JS::CallArgs args = JS::CallArgsFromVp(argc, vp);

    bool ok = true;

    JS::RootedObject obj(cx, args.thisv().toObjectOrNull());

    js_proxy_t *proxy = jsb_get_js_proxy(obj);

    TestJSB* cobj = (TestJSB *)(proxy ? proxy->ptr : NULL);

    JSB_PRECONDITION2( cobj, cx, false, "js_TestJSB_TestJSB_testString : Invalid Native Object");

    if (argc == 1) {

        const char* arg0 = nullptr;

        std::string arg0_tmp; ok &= jsval_to_std_string(cx, args.get(0), &arg0_tmp); arg0 = arg0_tmp.c_str();

        JSB_PRECONDITION2(ok, cx, false, "js_TestJSB_TestJSB_testString : Error processing arguments");

        cobj->testString(arg0);

        args.rval().setUndefined();

        

        /// c++ 调用 js 部分

        JSContext* jc = ScriptingCore::getInstance()->getGlobalContext();

//        jsval ret;

        ScriptingCore::getInstance()->evalString( "cpp_callback(5,100)" ); // js 全局方法

        /// c++ 调用 js 部分

        /// ScriptingCore::getInstance()->executeFunctionWithOwner(<#jsval owner#>, <#const char *name#>, <#uint32_t argc#>, <#jsval *vp#>) // 此方法可调用全局文件

        return true;

    }

    JS_ReportError(cx, "js_TestJSB_TestJSB_testString : wrong number of arguments: %d, was expecting %d", argc, 1);

    return false;

}


js 模块:

function cpp_callback(a, b) {
    cc.log("cpp return two integer: " + a + " " + b + "ssssssssssssssssssssssssssssssssss");
}

模拟器与移动端运行正常打印;



13.   区分native与web:

if(cc.sys.isNative)
{
    cc.log("platform is native !!!");
    var testJSB = new my.TestJSB();
    testJSB.testprint();
    testJSB.testString("pppppppppppppppppppppppp");
    testJSB.testInt(123);
    testJSB.testLong(999999999999);
    testJSB.testBool(true);
}
else
{
    cc.log("sys.platform is browser !!!");
}

js binding 部分完结;


14.   android版本编译部分;

编译android到当前项目下的proj.android中

控制台执行: 

cocos compile -p android

如果有jsb的部分要修改android.mk两处:

   - 第一处是在当前项目下runtime-src中的proj.android,导入classes文件夹下的cpp文件到android.mk中;

   - 第二处是在/cocos2d-x/cocos/scripting/js-bindings/proj.android/Android.mk进行binding.cpp文件添加;

完成后接续ndk编译尝试;



15.   疑难错误解答:


error: JS: assets/src/app.js:36:ReferenceError: my is not defined

查看AppDelegate.cpp是否没有注册要jsb的cpp函数;

如: sc->addRegisterCallback(register_all_JSBindingIOSWXManager);



error: cpp调用js方法传参问题: (这里可以放到任何一个cpp内:)

#include "scripting/js-bindings/manual/cocos2d_specifics.hpp"

#include "jsapi.h"

#include "jsfriendapi.h"

  1. bool TSScriptJS::RunFunction( std::string funName, std::string arg )  
  2. {  
  3.     std::string rStr = funName + "(\"" + arg + "\");";  // 注意这里的括号部分
  4.     jsval v1;  
  5.     JSBool r = ScriptingCore::getInstance()->evalString(rStr.c_str(), &v1);  
  6.     return r;  
  7. }  

例子: c++:



JSC 进行cocos js代码加密:

ter:  cocos jscompile -s /Users/fox/Documents/js -d /Users/fox/Documents/jsc 

-s:js文件路径

-d:jsc输出路径


拷贝项目内的js原文件夹:

js文件路径:

/Users/xxx/xxx/ClientC2DJs/src

/Users/xxx/xxx/ClientC2DJs/frameworks/cocos2d-x/cocos/scripting/js-bindings/script

执行代码:

cocos jscompile -s /Users/fox/Documents/js -d /Users/fox/Documents/jsc 


完成后替换项目中的两个文件夹:  ...cocos2d/jsbinding/script 不要替换jsbinding中的auto文件夹,  ...逻辑部分src 但是不要替换main;

完成后运行测试;



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kaitiren

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值