|
|
7 лет назад | |
|---|---|---|
| .. | ||
| README.md | 7 лет назад | |
| SConscript | 7 лет назад | |
| example_cplusplus.cpp | 7 лет назад | |
首先,不得不说明下JerryScript的基础类型:jerry_value_t。一个对象可以设定任意个属性,属性可以是number,string,function等,也可以是对象。但每个对象中,都有一个指针:native_pointer,这个指针就可用来存放或传递数据。
jerry_value_t obj
├── 属性1
├── 属性2
│ ...
│ ...
└── native_pointer
JerryScript中则提供了获取、设定native_pointer的API。
bool
jerry_get_object_native_pointer (const jerry_value_t obj_val,
void **out_native_pointer_p,
const jerry_object_native_info_t **out_native_info_p)
bool
jerry_set_object_native_pointer (const jerry_value_t obj_val,
void *native_p,
const jerry_object_native_info_t *info_p)
此Package中,我们一般使用以下的宏在JerryScript中创建一些接口,来使用C++的API:
#define REGISTER_HANDLER(NAME) \
jerryx_handler_register_global ( (jerry_char_t *)# NAME, NAME ## _handler)
#define REGISTER_HANDLER_ALIAS(NAME, HANDLER) \
jerryx_handler_register_global ( (jerry_char_t *)# NAME, HANDLER)
#define REGISTER_METHOD(OBJ, NAME) \
js_add_function (OBJ, # NAME, NAME ## _handler)
#define REGISTER_METHOD_ALIAS(OBJ, NAME, HANDLER) \
js_add_function (OBJ, # NAME, HANDLER)
#define REGISTER_METHOD_NAME(OBJ, NAME, HANDLER) \
js_add_function (OBJ, NAME, HANDLER ## _handler)
可以看到,前两个宏指向函数jerryx_handler_register_global,具体内容如下:
jerry_value_t
jerryx_handler_register_global (const jerry_char_t *name_p, /**< name of the function */
jerry_external_handler_t handler_p) /**< function callback */
{
jerry_value_t global_obj_val = jerry_get_global_object ();
jerry_value_t function_name_val = jerry_create_string (name_p);
jerry_value_t function_val = jerry_create_external_function (handler_p);
jerry_value_t result_val = jerry_set_property (global_obj_val, function_name_val, function_val);
jerry_release_value (function_val);
jerry_release_value (function_name_val);
jerry_release_value (global_obj_val);
return result_val;
}
后三个宏定义都指向了函数js_add_function,具体内容如下:
void js_add_function(const jerry_value_t obj, const char *name,
jerry_external_handler_t func)
{
jerry_value_t str = jerry_create_string((const jerry_char_t *)name);
jerry_value_t jfunc = jerry_create_external_function(func);
jerry_set_property(obj, str, jfunc);
jerry_release_value(str);
jerry_release_value(jfunc);
}
从上述代码中可以看到jerryx_handler_register_global和js_add_function的实质操作就是在指定对象中加入一个名为name的func,这个obj可以指定为全局obj。而我们就只需要在这个func中添加C++的代码并使用API,并且可以把所需要的数据作为属性加入到指定JerryScript对象中或返回出来。如果想要在JS中传递C++对象,我们就可以利用文章开头所说的native_pointer
此func类型为jerry_external_handler_t,具体定义如下。
typedef jerry_value_t (*jerry_external_handler_t) (const jerry_value_t function_obj,
const jerry_value_t this_val,
const jerry_value_t args_p[],
const jerry_length_t args_count);
为了方便书写代码,Package中添加了对应的宏定义。
#define DECLARE_HANDLER(NAME) \
static jerry_value_t \
NAME ## _handler (const jerry_value_t func_value, \
const jerry_value_t this_value, \
const jerry_value_t args[], \
const jerry_length_t args_cnt )
以添加request接口为例
创建一个初始化API:js_request_init,并设定入参变量obj。创建好初始化API后,我们就只要在API中执行REGISTER_METHOD(obj, request),但此时函数request还未创建,那我们只需要创建它即可。而函数request内部,我们就可以添加C++的API,执行我们需要操作或把相关数据转换成JerryScript的数据类型返回出来。
DECLARE_HANDLER(request)
{
//此处就能添加对应的C++的API,并执行具体内容。
}
extern "C"
{
int js_request_init(jerry_value_t obj)
{
REGISTER_METHOD(obj, request);
return 0;
}
}
譬如在此Package中,JerryScript的执行函数为jerry_main,那我们就还需要在jerry_main中执行下js_request_init。
extern int js_request_init(jerry_value_t obj);
int jerry_main(int argc, char** argv)
{
//...
jerry_value_t global_object = jerry_get_global_object();
js_request_init(global_object);
//...
}
本示例示仅范了如何导入C++的API,并在创建出一个与C++对象对应的JS对象,还需要在执行函数中执行js_example_rect_init
#include <rtthread.h>
#include <jerry_util.h>
/*自定义C++类*/
class Rectangle
{
private:
int length;
int width;
public:
Rectangle(int length,int width);
int getSize();
int getLength();
int getWidth();
};
Rectangle::Rectangle(int length,int width)
{
this->length = length;
this->width = width;
}
int Rectangle::getSize()
{
return (this->length * this->width);
}
int Rectangle::getLength()
{
return this->length;
}
int Rectangle::getWidth()
{
return this->width;
}
/**********/
void rectangle_free_callback(void *native_p)
{
Rectangle* rect = (Rectangle*)native_p;
delete(rect);
}
const static jerry_object_native_info_t rectangle_info =
{
rectangle_free_callback //当js_rect对象释放后,调用该回调函数
};
DECLARE_HANDLER(getSize)
{
void *native_pointer = RT_NULL;
jerry_get_object_native_pointer(this_value,&native_pointer,RT_NULL); //获取当前对象中的native_pointer
if(native_pointer)
{
/*调用C++对象的API,并将其返回值转换成JS对象*/
Rectangle* rectangle = (Rectangle*)native_pointer;
jerry_value_t js_size = jerry_create_number(rectangle->getSize());
return js_size;
}
return jerry_create_undefined();
}
DECLARE_HANDLER(getLength)
{
void *native_pointer = RT_NULL;
jerry_get_object_native_pointer(this_value,&native_pointer,RT_NULL); //获取当前对象中的native_pointer
if(native_pointer)
{
/*调用C++对象的API,并将其返回值转换成JS对象*/
Rectangle* rectangle = (Rectangle*)native_pointer;
jerry_value_t js_length = jerry_create_number(rectangle->getLength());
return js_length;
}
return jerry_create_undefined();
}
DECLARE_HANDLER(getWidth)
{
void *native_pointer = RT_NULL;
jerry_get_object_native_pointer(this_value,&native_pointer,RT_NULL); //获取当前对象中的native_pointer
if(native_pointer)
{
/*调用C++对象的API,并将其返回值转换成JS对象*/
Rectangle* rectangle = (Rectangle*)native_pointer;
jerry_value_t js_width = jerry_create_number(rectangle->getWidth());
return js_width;
}
return jerry_create_undefined();
}
DECLARE_HANDLER(rectangle)
{
/*入参判断*/
if(args_cnt !=2 || !jerry_value_is_number(args[0]) || !jerry_value_is_number(args[1]))
return jerry_create_undefined();
jerry_value_t js_rect = jerry_create_object(); //创建JS对象 js_rect
Rectangle* rectangle = new Rectangle(jerry_get_number_value(args[0]),jerry_get_number_value(args[1])); //创建C++对象 rectangle
jerry_set_object_native_pointer(js_rect, rectangle,&rectangle_info); //把js_rect的native_pointer指向rectangle
/*调用rectangle的API,并把其返回值转换成JS对象*/
jerry_value_t js_length = jerry_create_number(rectangle->getLength());
jerry_value_t js_width = jerry_create_number(rectangle->getWidth());
/*把js_length 和 js_width设置成js_rect的属性,类Rectangle中lenght与width为私有变量,如要JS对象与C++对象保持对应,此处代码可注释掉*/
js_set_property(js_rect,"length",js_length);
js_set_property(js_rect,"width",js_width);
jerry_release_value(js_length);
jerry_release_value(js_width);
REGISTER_METHOD(js_rect,getSize); //为js_retc注册一个方法getSize
REGISTER_METHOD(js_rect,getLength); //为js_retc注册一个方法getLength
REGISTER_METHOD(js_rect,getWidth); //为js_retc注册一个方法getWidth
return js_rect;
}
extern "C"
{
int js_example_rect_init(jerry_value_t obj)
{
REGISTER_METHOD(obj, rectangle); //为指定对象obj注册一个方法rectangle_init,这个对象可以是global_obj
return 0;
}
}