本文通过一个例子讲述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;
}
}
再创建JSBaseTv.cpp, registerScanCallback用以javascript来注册callback函数。channelScanCallback保存回调函数,triggerScanCallback用以触发回调函数。
#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);
}
}
修改JAVASCRIPT
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);
}
}