js call c++

0.声明

TT命名空间  类名test

1.创建一个 2dx 的 js 项目。

2.新创建一个 jsbRegister.cpp 文件,jsbRegister.h文件中声明一个全局方法。   

#include <iostream>

#include "jsapi.h"

#include "jsfriendapi.h"

#include "ScriptingCore.h"


#include "test.h"


void register_jsb(JSContext* cx,JSObject* obj);

3. 2dx 的 AppDelegate.cpp 中引进头文件,jsbRegister.h

  ScriptingCore* sc = ScriptingCore::getInstance();

  sc->addRegisterCallback(register_jsb);

  sc->start();

4. jsbRegister.cpp 去实现这个方法

#include "jsbRegister.h"

#include "cocos2d.h"

#include "cocos2d_specifics.hpp"


JSClass*        jsb_class;//全局变量

JSObject*       jsb_prototype;


void register_jsb(JSContext* cx, JSObject* obj)//注册:全局函数
{
    jsval nsval;
    JSObject* ns;
    JS_GetProperty(cx, obj, "TT", &nsval);//c++ 命名空间绑定
    
    if (nsval == JSVAL_VOID)
    {
        ns = JS_NewObject(cx, NULL, NULL, NULL);
        nsval = OBJECT_TO_JSVAL(ns);
        JS_SetProperty(cx, obj, "TT", &nsval);//命名空间绑定
    }else
    {
        JS_ValueToObject(cx, nsval, &ns);
    }
    
    obj = ns;
    
    js_register(cx, obj);               //调用:绑定类的方法
    
    
    //JS_DefineFunction:调用全局方法
    JS_DefineFunction(cx, jsb_prototype, "retain", JSB_cocos2dx_retain, 0, JSPROP_READONLY | JSPROP_PERMANENT);
    JS_DefineFunction(cx, jsb_prototype, "release", JSB_cocos2dx_release, 0, JSPROP_READONLY | JSPROP_PERMANENT);
}

js_register(cx, obj);  全局方法,创建 c++ 类的对象。


JS_DefineFunction(cx, jsb_prototype,"retain", JSB_cocos2dx_retain,0, JSPROP_READONLY |JSPROP_PERMANENT);

通过 js 对象调用 retain 方法可以执行 c++ 全局方法 JSB_cocos2dx_retain

var testJSB = new TT.test();//创建 js 绑定的 c++对象

testJSB.retain();

testJSB.release();

//retain时候调用
JSBool JSB_cocos2dx_retain(JSContext* cx, uint32_t argc, jsval *vp)
{
    CCLog("JSB_cocos2dx_retain   ----------  JSB_cocos2dx_retain");
    
    JSObject* thisObj = JS_THIS_OBJECT(cx, vp);
    
    if (thisObj)
    {
        js_proxy_t* proxy = jsb_get_js_proxy(thisObj);//2dx
        
        if (proxy)
        {
            ((CCObject* )proxy->ptr)->retain();
            CCLog("Retain succeed!");
            return JS_TRUE;
        }
    }
    
    JS_ReportError(cx, "Invaild native object");
    return JS_FALSE;
}


//释放内存调用
JSBool JSB_cocos2dx_release(JSContext* cx, uint32_t argc, jsval *vp)
{
    CCLog("JSB_cocos2dx_release   ----------  JSB_cocos2dx_release");
    
    JSObject* thisObj = JS_THIS_OBJECT(cx, vp);
    
    if (thisObj)
    {
        js_proxy_t* proxy = jsb_get_js_proxy(thisObj);
        
        if (proxy)
        {
            ((CCObject* )proxy->ptr)->release();
            CCLog("Release succeed!");
            return JS_TRUE;
        }
    }
    
    JS_ReportError(cx, "Invaild native object");
    return JS_FALSE;
}


5.jsbRegister.cpp  js绑定c++对象方法

//注册 一些可能被调用的函数
void js_register(JSContext* cx, JSObject* global)
{
    CCLog("js_register   ----------  js_register");
    
    jsb_class = (JSClass *)calloc(1, sizeof(JSClass));
    jsb_class->name = "test";//类名
    
    jsb_class->addProperty = JS_PropertyStub;
    jsb_class->delProperty = JS_PropertyStub;
    jsb_class->getProperty = JS_PropertyStub;
    jsb_class->setProperty = JS_StrictPropertyStub;
    jsb_class->enumerate = JS_EnumerateStub;
    jsb_class->resolve = JS_ResolveStub;
    jsb_class->convert = JS_ConvertStub;
    jsb_class->finalize = js_finalize;//类型析构函数绑定
    jsb_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2);
    
    /*
     等呆研究
     */
    static JSPropertySpec properties[] =
    {
        {0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}
    };
    
    
    /*
     js 调用 functionTest 方法触发 js_functionTest
     */
    static JSFunctionSpec funcs[] =
    {
        JS_FN("functionTest", js_functionTest, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
        JS_FS_END
    };
    
    
    /*
     js 调用 create 方法触发 js_create
     */
    static JSFunctionSpec st_funcs[] =
    {
        JS_FN("create", js_create, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE),
        JS_FS_END
    };
    
    
    /*
     JS_InitClass:调用对象方法
     1:js_constructor 创建类对象注册到 js
     2:funcs 注册 js 调用的对象方法
     3:st_funcs 注册 js 调用的静态方法
     4:properties (可能是注册属性  猜测)
     */
    jsb_prototype = JS_InitClass(cx, global, NULL, jsb_class, js_constructor, 0, properties, funcs, NULL, st_funcs);
    JSBool found;
    
    
    JS_SetPropertyAttributes(cx, global, "TT", JSPROP_ENUMERATE | JSPROP_READONLY, &found);//命名空间
    TypeTest<TT::test> t;//对象
    
    
    js_type_class_t* p;
    uint32_t typeId = t.s_id();//次类对象的唯一标示符
    HASH_FIND_INT(_js_global_type_ht, &typeId, p);
    
    
    if (!p)//绑定对象和方法到 js 上
    {
        p = (js_type_class_t* )malloc(sizeof(_js_global_type_ht));
        p->type = typeId;
        p->jsclass = jsb_class;
        p->proto = jsb_prototype;
        p->parentProto = NULL;
        HASH_ADD_INT(_js_global_type_ht, type, p);
    }
}


void js_finalize(JSFreeOp* fop,JSObject* obj)//一直没有被成功调用过 ???

{

    CCLog("js_finalize   ----------  js_finalize");

    CCLOGINFO("JSBindings: finallizing JS object %p JSB", obj);

}

 

JS_InitClass(cx, global, NULL,jsb_class, js_constructor, 0, properties, funcs, NULL, st_funcs);

var testJSB = new TT.test();  new 时候调用 js_constructor 全局方法


var testJSB = TT.test.create(); 调用 js_create

testJSB.functionTest();调用  js_functionTest


6.jsbRegister 两张在 js绑定中创建 c++ 对象

 
//new创建类对象,并绑定到js
JSBool js_constructor(JSContext* cx, uint32_t argc, jsval* vp)
{
    cocos2d::CCLog("JS Constructor...");
    if (argc == 0)
    {
        TT::test* cobj = new TT::test();//创建注册到 js中 类的对象
        cocos2d::CCObject* ccobj = dynamic_cast<cocos2d::CCObject*>(cobj);
        if (ccobj) ccobj->autorelease();//2dx 创建对象以后就直接 autorelease
        
        
        TypeTest<TT::test> t;
        
        js_type_class_t* typeClass;
        uint32_t typeId = t.s_id();
        HASH_FIND_INT(_js_global_type_ht, &typeId, typeClass);
        assert(typeClass);
        JSObject* obj = JS_NewObject(cx, typeClass->jsclass, typeClass->proto, typeClass->parentProto);
        JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
        

        js_proxy_t* p = jsb_new_proxy(cobj, obj);//2dx
        
        JS_AddNamedObjectRoot(cx, &p->obj, "TT::test");//
        
        
        return JS_TRUE;
    }
    
    JS_ReportError(cx, "Wrong number of arguments: %d, was expecting: %d", argc, 0);
    
    return JS_FALSE;
}

//create创建对象时候调用
JSBool js_create(JSContext* cx, uint32_t argc, jsval* vp)
{
    cocos2d::CCLog("js is creating...");
    if (argc == 0)
    {
        TT::test* ret = TT::test::create();
        
        jsval jsret;
        do
        {
            if (ret)
            {
                js_proxy_t* proxy = js_get_or_create_proxy<TT::test>(cx, ret);
                
                jsret = OBJECT_TO_JSVAL(proxy->obj);
            }else
            {
                jsret = JSVAL_NULL;
            }
        } while(0);
        JS_SET_RVAL(cx, vp, jsret);
        
        return JS_FALSE;
    }
    
    JS_ReportError(cx, "Wrong number of arguments");
    
    return JS_FALSE;
}


7. js 通过 jsb 调用 c++的对象方法

通过前面的注册,可以用 js 去调用 c++ 的全局方法,js_functionTest 在前面  js_register 被注册过了。

var testJSB = new TT.test();

testJSB.functionTest(); 先调用 jsb方法 functionTest 在通过前面的注册调用c++方法

//调用JSBinding 里的 functionTest 方法
JSBool js_functionTest(JSContext* cx, uint32_t argc, jsval* vp)
{
    CCLog("js_functionTest   ---   js_functionTest");
    
    JSBool ok = JS_TRUE;
    JSObject* obj = NULL;
    TT::test* cobj = NULL;
    
    
    obj = JS_THIS_OBJECT(cx, vp);
    js_proxy_t* proxy = jsb_get_js_proxy(obj);//2dx

    cobj = (TT::test* )(proxy ? proxy->ptr : NULL);//通过代理得到自己创建的那个类的对象
    
    
    JSB_PRECONDITION2(cobj, cx, JS_FALSE, "Invalid Native Object");
    
    
    if (argc == 0)
    {
        cobj->functionTest();//调用 TT::test 类对象方法
        JS_SET_RVAL(cx, vp, JSVAL_VOID);
        return ok;
    }
    
    JS_ReportError(cx, "Wrong number of arguments");
    return JS_FALSE;
}

8.自己的 c++类

test.h

#ifndef __myJSB__test__
#define __myJSB__test__

#include <iostream>
#include "cocos2d.h"
#include "ScriptingCore.h"

namespace TT
{
    
    class test: public cocos2d::CCObject
    {
    public:
        static cocos2d::CCScene* scene();
        
        test();
        ~test();
        
        virtual bool init();
        CREATE_FUNC(test);
        void functionTest();
        
    };
}



#endif

test.cpp

#include "test.h"


bool TT::test::init()
{
    bool bRef = false;
    do
    {
        cocos2d::CCLog("TT::test init...");
        bRef = true;
    } while (0);
    
    
    return bRef;
}


void TT::test::functionTest()
{
    cocos2d::CCLog("TT::test test...");

}

TT::test::test(){}
TT::test::~test()// js执行对象 release方法时候调用
{
    CCLog("~test");

}



































你可能感兴趣的:(js call c++)