绑定全局函数
本节介绍了如何绑定全局函数
例子
假设我们有一个简单的Add
函数:
|
|
我们和绑定变量一样绑定他到全局对象。只是使用JS_NewCFunction
创建JSValue
:
|
|
注意JS_NewCFunction
的第二个参数AddFnBinding
。他的类型是JSCFunction
,一个函数指针:
|
|
QuickJS在看到JS调用C++函数时其实会调用我们给的这个函数指针。我们需要实现此函数指针并且在内部调用我们自己的C++函数:
|
|
参数解释:
ctx
:JS上下文self
:如果函数是类对象函数,那这里会传入类对象。否则是JS_UNDEFINED
argc
:传给函数的参数格式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 4
JSCFunctionType 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);