本文通过一个例子讲述javascript如何注册一个函数到中间件,中间件如何调用这个函数,传递相关的参数。
先创建头文件JSBaseTv.h声明一个c++的类,包含两个函数和一个变量:
#include <JavaScriptCore/JavaScript.h> using namespace std; namespace Sample { class JSBaseTv { public: static JSValeRef registerScanCallback(JSContextRef ctx, JSObjectRef function,JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],JSValueRef *exception); static JSValueRef triggerScanCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception); private: statice JSObjectRef channelScanCallback; } }
#include <JavaScriptCore/JavaScript.h> #include "JSBaseTv.h" using namespace std; namespace Sample { JSObjectRef JSBaseTv::channelScanCallback; JSValeRef registerScanCallback(JSContextRef ctx, JSObjectRef function,JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],JSValueRef *exception) { if(argumentCount < 1) { *exception = JSValueMakeString(ctx, JSStringCreateWithUTF8CString("scan callback argument invalid.")); return JSValueMakeNull(ctx); } JSObjectRef cb = const_cast<JSObjectRef>(arguments[0]); if(!JSObjectIsFunction(ctx,cb)) { channelScanCallback = NULL; return JSValueMakeNull(ctx); } channelScanCallback = cb; return JSValueMakeNull(ctx); } JSValueRef triggerScanCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) { if(channelScanCallback == NULL) { *exception = JSValueMakeString(ctx, JSStringCreateWithUTF8CString("callback is null.")); return JSValueMakeNull(ctx); } //just for testing. JSValueRef args[3]; args[0] = JSValueMakeNumber(ctx,15); args[1] = JSValueMakeNumber(ctx,7); args[2] = JSValueMakeNumber(ctx,18); JSObjectCallAsFunction(ctx,channelScanCallback,NULL,3,args,NULL); return JSValueMakeNull(ctx); } }
triggerScanCallback返回了三个参数。
再建立一个javascript 文件JSBaseTv.js
var sample = { register:function() { .... //register callback; $BaseTv.registerScanCallback(sample.handleCallback); .... } handleCallback:function(tvNum, radioNum, progress) { alert("tvNum " + tvNum); alert("radioNum " + radioNum); alert("progress " + progress); } }
register函数把handleCallback注册下去。当triggerScanCallback调用时,handleCallback被调用,在这个例子中它会得到15,7,18这三个值。
我们也可以将参数封装在一个结构里面。如下:
JSValueRef triggerScanCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) { if(channelScanCallback == NULL) { *exception = JSValueMakeString(ctx, JSStringCreateWithUTF8CString("callback is null.")); return JSValueMakeNull(ctx); } //just for testing. JSValueRef args[1]; /* create an object */ JSObjectRef para = JSObjectMake(ctx,NULL,NULL); //create four properties: type, arg0, arg1, arg2 JSStringRef eventType = JSStringCreateWithUTF8CString("type"); JSStringRef name = JSStringCreateWithUTF8CString("eventChannelScanProgress"); JSValueRef eventName = JSValueMakeString(ctx,name); JSStringRef argName0 = JSStringCreateWithUTF8CString("arg0"); JSValueRef argVal0 = JSValueMakeNumber(ctx,20); JSStringRef argName1 = JSStringCreateWithUTF8CString("arg1"); JSValueRef argVal1 = JSValueMakeNumber(ctx,21); JSStringRef argName2 = JSStringCreateWithUTF8CString("arg2"); JSValueRef argVal2 = JSValueMakeNumber(ctx,50); /* set the value for each property */ JSObjectSetProperty(ctx,para,eventType,eventName,kJSPropertyAttributeNone,0); JSObjectSetProperty(ctx,para,argName0,argVal0,kJSPropertyAttributeNone,0); JSObjectSetProperty(ctx,para,argName1,argVal1,kJSPropertyAttributeNone,0); JSObjectSetProperty(ctx,para,argName2,argVal2,kJSPropertyAttributeNone,0); args[0] = para; JSObjectCallAsFunction(ctx,channelScanCallback,NULL,1,args,NULL); return JSValueMakeNull(ctx); } }
var sample = { register:function() { .... //register callback; $BaseTv.registerScanCallback(sample.handleCallback); .... } handleCallback:function(evt) { alert("event type:" + evt.type); alert("tvNum " + evt.arg0); alert("radioNum " + evt.arg1); alert("progress " + evt.arg2); } }