绑定全局函数
本节介绍了如何绑定全局函数
例子
假设我们有一个简单的Add函数:
| |
我们和绑定变量一样绑定他到全局对象。只是使用JS_NewCFunction创建JSValue:
| |
注意JS_NewCFunction的第二个参数AddFnBinding。他的类型是JSCFunction,一个函数指针:
| |
QuickJS在看到JS调用C++函数时其实会调用我们给的这个函数指针。我们需要实现此函数指针并且在内部调用我们自己的C++函数:
| |
参数解释:
ctx:JS上下文self:如果函数是类对象函数,那这里会传入类对象。否则是JS_UNDEFINEDargc:传给函数的参数格式argv:传给函数的参数。注意这里写的虽是JSValueConst但并不代表他们是常量。因为底层定义如下:1#define JSValueConst JSValue
这里首先检查参数个数和参数类型是否是我们想要的,然后将两个参数使用JS_ToXXX转换成C++类型,然后调用我们的Add函数并将结果穿给JSValue。
更多函数类型
QuickJS内置了很多函数类型。JSCFunction只是最通用和最常见的类型。还有如下类型(定义在JSCFunctionEnum):
JS_CFUNC_generic:最通用的函数类型(就是我们使用的JSCFunction)JS_CFUNC_constructor:类的构造函数- 专门给数学函数定义的类型:
JS_CFUNC_f_f:形如double(*)(double)的函数指针
JS_CFUNC_f_f_f:形如double(*)(double, double)的函数指针JS_CFUNC_getter和JS_CFUNC_setter:getter和setterJS_CFUNC_iterator_next:用于迭代器的类型JS_CFUNC_constructor_or_func:<不清楚是什么,以后研究>- 以及某些函数的magic版本(在类型后面加
_magic例如JS_CFUNC_generic_magic)
这些函数的签名可以在JSCFunctionType看到:
| |
数学函数类型
JS_CFUNC_f_f和JS_CFUNC_f_f_f。
这两个函数都是接收double作为参数(f_f接收一个,f_f_f接收两个),返回一个double值。一般用于绑定sin,cos这种数学函数。优点是函数签名不含JSValue直接是double,不需要做额外的转换。
getter和setter
用于变量的Getter和Setter。可以使用这种方式实现只读变量(只实现getter不实现setter)。函数签名分别是:
Getter:JSValue (*getter)(JSContext *ctx, JSValueConst this_val)。传入要获得值的对象Setter:JSValue (*setter)(JSContext *ctx, JSValueConst this_val, JSValueConst val)。传入值的来源val和放入值的变量this_val
迭代器类型
<暂时没研究,之后补上>
带有magic的类型
几乎所有类型的函数都有magic版本。magic版本的作用是通过额外的参数int magic来将多个函数聚合在一起:
| |
使用JS_NewCFunctionMagic来绑定magic函数。通过最后的参数来区分内部到底是在使用哪个函数。
如何绑定这些花里胡哨的函数类型
虽然函数类型和签名很多,但是JS_SetPropertyStr的第二个参数只接收JSCFunction类型。要如何绑定呢?有两种方法:
使用特定的绑定函数,比如magic相关的就是
JS_NewCFunctionMagic,getter/setter就是JS_DefinePropertyGetSet()使用
JSCFunctionType进行转换:1 2 3 4JSCFunctionType fn_type; // JS_CFUNC_f_f_f pass two double elem and return one double elem fn_type.f_f_f = +[](double param1, double param2) -> double { return param1 + param2; }; JSValue fn = JS_NewCFunction2(ctx, fn_type.generic, "Sum", 1, JS_CFUNC_f_f_f, 0);