• MuJS官网示例讲解


    MuJS官网示例讲解
    原创炼气士 最后发布于2018-03-06 14:37:41 阅读数 736 收藏
    展开
    前提:已经在linux中安装好MuJS,MuJS安装比较简单,参考安装包中的readme文件
    本章介绍的环境:vm+centos6.5 32bit
    官网示例链接:http://dev.mujs.com/docs/examples.html

    示例1
    A stand-alone interpreter
    interpreter.c

    #include <stdio.h>
    #include <mujs.h>

    int main(int argc, char **argv)
    {
    char line[256];
    int ret;
    //js_State *J = js_newstate(NULL, NULL, 0);
    js_State *J = js_newstate(NULL, NULL, JS_STRICT);
    //printf("JS_STRICT:%d ", JS_STRICT);
    while(fgets(line, sizeof(line), stdin))
    {
    ret=js_dostring(J, line);
    //printf("dostring ret:%d ", ret);
    }
    js_freestate(J);

    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    标题:一个独立的解释器
    功能:借助mujs的库用C实现的一个javascript脚本解释器;编译和运行由标准输入得到的js脚本命令,如果脚本有错误,则返回错误信息。
    下面是编译操作,我这里加上了g选项用于gdb调试


    执行结果如下

    输入var a = 1; 回车系统执行成功,未报异常;输入b=2则返回异常,提示b变量未定义。在一般的javascript模式下定义变量不带var是可以的,但在strict严格模式下不带var是不允许的。
    在mujs.h中找到JS_STRICT的宏定义,flag标记只有一个值

    /* State constructor flags */
    enum {
    JS_STRICT = 1,
    };
    1
    2
    3
    4
    下面做个尝试,将flag设置为0 ,即执行代码

    js_State *J = js_newstate(NULL, NULL, 0);
    1
    编译后,我们可以看到在终端中输入b=0时就没有上报异常了。

    我们结合前一篇参考手册中js_dostring函数的说明来看
    函数原型

    int js_dostring(js_State *J, const char *source);
    // J为js_State指针,与c进行交互的关键集合,需要先进行创建,
    // source为javascript脚本,字符串格式。
    // 如果发生错误,调用report上报异常,并返回1; 返回0表示成功。
    1
    2
    3
    4
    所以放开interpreter.c中的注释,可以看到执行成功时ret的值为0,失败时为1。

    下面我们重点看看js_State结构体,这个太重要了,javascript和c的互相作用就靠它了,在文件jsi.h中可以找到定义。

    /* State struct */

    struct js_State
    {
    void *actx;
    void *uctx;
    js_Alloc alloc;
    js_Report report;
    js_Panic panic;

    js_StringNode *strings;

    int default_strict;
    int strict;

    ......
    ......

    int nextref; /* for js_ref use */
    js_Object *R; /* registry of hidden values */
    js_Object *G; /* the global object */
    js_Environment *E; /* current environment scope */
    js_Environment *GE; /* global environment scope (at the root) */

    /* execution stack */
    int top, bot;
    js_Value *stack;

    /* garbage collector list */
    int gcmark;
    int gccounter;
    js_Environment *gcenv;
    js_Function *gcfun;
    js_Object *gcobj;
    js_String *gcstr;

    /* environments on the call stack but currently not in scope */
    int envtop;
    js_Environment *envstack[JS_ENVLIMIT];

    /* debug info stack trace */
    int tracetop;
    js_StackTrace trace[JS_ENVLIMIT];

    /* exception stack */
    int trytop;
    js_Jumpbuf trybuf[JS_TRYLIMIT]; //异常跟踪 jump_buf类型,被setjmp调用。
    };
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    结构体中的注释已经很清楚了,里面stack有:
    1.execution stack
    2.environments on the call stack but currently not in scope
    3.debug info stack trace
    4.exception stack

    示例2
    Hello, world!
    hello.c

    //Hello, world!

    #include <stdio.h>
    #include <mujs.h>

    static void hello(js_State *J)
    {
    const char *name = js_tostring(J, 1);
    printf("Hello, %s! ", name);
    js_pushundefined(J);
    }

    int main(int argc, char **argv)
    {
    js_State *J = js_newstate(NULL, NULL, JS_STRICT);

    js_newcfunction(J, hello, "hello", 1);
    js_setglobal(J, "hello"); //设置为全局变量

    js_dostring(J, "hello('world');"); // 调用javascript

    js_freestate(J); // 释放J
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    执行结果为:
    Hello world!
    基本的逻辑如下图,hello函数是自定义的函数,用c语言实现,并封装为“js_CFunction”类型。javascript脚本通过js_newcfunction创建(注册)hello函数。然后c主程序调用js_dostring函数加载js脚本,在脚本中hello(‘world)’就是完成对hello函数的调用,带入的’world’为传入参数。

    我们逐行代码解读,在进入到函数内部是,点到为止,不再深入。

    首先看看hello函数

    // 函数定义遵循js_CFunction的函数指针定义
    // 在mujs中js_CFunction的定义为
    // typedef void (*js_CFunction)(js_State *J);
    static void hello(js_State *J)
    {
    // 从J->stack的1位置获取参数1,本例只有1个参数,且参数类型为
    // string,所以调用js_tostring(J, 1)
    const char *name = js_tostring(J, 1);
    printf("Hello, %s! ", name);
    js_pushundefined(J); // 无返回值,压入undefined补全
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef void (*js_CFunction)(js_State *J);
    /*
    由定义可知,创建javascript脚本可调用的函数,返回类型void, 函数参数只有js_State *J。
    */
    1
    2
    3
    4
    现在对程序进行修改,加深对J->stack的理解

    #include <stdio.h>
    #include <mujs.h>

    static void hello(js_State *J)
    {
    const char *name = js_tostring(J, 1);
    int num = js_tonumber(J, 2); // 获取第二个参数
    printf("Hello, %s! num:%d ", name, num);
    js_pushundefined(J);
    }


    int main(int argc, char **argv)
    {
    js_State *J = js_newstate(NULL, NULL, JS_STRICT);

    js_newcfunction(J, hello, "hello", 2);// 2个参数

    js_setglobal(J, "hello");

    js_dostring(J, "hello('world',100);");

    js_freestate(J);

    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    执行结果
    Hello, world! num:100

    再修改为简单一点的调用,这样便于我们理解参考手册中参数的放置顺序
    printargs.c

    #include <stdio.h>
    #include <mujs.h>


    static void printargs(js_State *J)
    {
    int this_value = js_tonumber(J, 0);
    int arg1 = js_tonumber(J, 1);
    int arg2 = js_tonumber(J, 2);
    int negative_arg1 = js_tonumber(J, -1);
    int negative_arg2 = js_tonumber(J, -2);
    int negative_this_value = js_tonumber(J, -3);
    printf("this value:%x ", this_value);
    printf("arg1:%d ", arg1);
    printf("arg2:%d ", arg2);
    printf("negative arg1:%d ", negative_arg1);
    printf("negative arg2:%d ", negative_arg2);
    printf("negative this value:%x ", negative_this_value);

    }

    int main(void)
    {
    js_State *J = js_newstate(NULL, NULL, JS_STRICT);
    js_newcfunction(J, printargs, "printargs", 2);
    js_setglobal(J, "printargs");
    js_dostring(J, "printargs(1,2);");

    js_freestate(J);
    return 0;

    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    编译后执行结果

    [root@bogon javascript]# gcc printargs.c -lmujs -g -o printargs
    [root@bogon javascript]# ./printargs
    this value:80000000
    arg1:1
    arg2:2
    negative arg1:2
    negative arg2:1
    negative this value:8000000

    js_State->stack中的参数和this value排序如图,正序从下往上0,1,2;逆序从上往下,-1,-2,-3。this value的值为0x80000000,属于无效值。

    示例3
    Configuration file
    从config.js脚本中加载全局变量
    config.js,包含全局变量foo coo 和 局部变量boo

    var foo=2;
    var coo = "string"
    function afunc()
    {
    var boo = 100;
    }
    1
    2
    3
    4
    5
    6
    config_file.c

    #include <stdio.h>
    #include <mujs.h>


    int main(void)
    {
    js_State *J = js_newstate(NULL, NULL, JS_STRICT);
    js_dofile(J, "config.js"); // 加载js文件
    js_getglobal(J, "foo"); // 获取js中的全局变量foo
    int foo = js_tonumber(J, -1);
    printf("foo: %d ", foo);
    js_pop(J,1); // 弹出栈顶1个元素,即foo
    foo = 0;
    // js_getglobal(J, "foo"); // 如放开注释,foo可以再次获取
    foo = js_tonumber(J, -1); // 此时再获取foo,则已经没有了
    printf("foo: %d ", foo);
    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    编译后执行结果

    [root@bogon javascript]# ./config_file
    foo: 2
    foo: -2147483648
    1
    2
    3


    修改一下例子,再看看
    config_file_ex.c

    #include <stdio.h>
    #include <mujs.h>

    int main(void)
    {
    js_State *J = js_newstate(NULL, NULL, JS_STRICT);
    js_dofile(J, "config.js");
    js_getglobal(J, "foo");
    js_getglobal(J, "coo");
    js_getglobal(J, "boo");
    int foo = js_tonumber(J, -3);
    char *coo = js_tostring(J, -2);
    int boo = js_tonumber(J, -1);
    printf("foo: %d ", foo);
    printf("coo: %s ", coo);
    printf("boo: %d ", boo);
    js_pop(J,1);
    foo = 0;
    foo = js_tonumber(J, -2);
    coo = NULL;
    coo = js_tostring(J, -1);
    printf("foo: %d ", foo);
    printf("coo: %s ", coo);
    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    执行结果

    [root@bogon javascript]# ./config_file_ex1
    foo: 2
    coo: string
    boo: -2147483648
    foo: 2
    coo: string
    1
    2
    3
    4
    5
    6
    局部变量boo无法获取,在执行js_getglobal(J, “boo”)时,也会压入一个空值undefined。

    再看一个例子
    config_file_ex2.c

    #include <stdio.h>
    #include <mujs.h>

    int main(void)
    {
    js_State *J = js_newstate(NULL, NULL, JS_STRICT);
    js_dofile(J, "config.js");
    js_getglobal(J, "coo"); /* js全局变量 */
    js_getglobal(J, "foo"); /* js全局变量 */
    js_getglobal(J, "doo"); /* 无效 */
    js_getglobal(J, "eoo"); /* 无效 */
    char *coo = js_tostring(J, -4);
    int foo = js_tonumber(J, -3);
    int doo = js_tonumber(J, -2);
    int eoo = js_tonumber(J, -1);
    printf("foo: %d ", foo);
    printf("coo: %s ", coo);
    printf("doo: %d ", doo);
    printf("eoo: %d ", eoo);
    js_pop(J,2);
    coo = js_tostring(J, -2);
    foo = js_tonumber(J, -1);
    printf("*******poped******* ");
    printf("foo: %d ", foo);
    printf("coo: %s ", coo);

    return 0;

    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    执行结果

    [root@bogon javascript]# ./config_file_ex2
    foo: 2
    coo: string
    doo: -2147483648
    eoo: -2147483648
    *******poped*******
    foo: 2
    coo: string
    1
    2
    3
    4
    5
    6
    7
    8
    doo和eoo没有,所以获取失败,但也会压栈占用堆栈空间;栈顶排序和js脚本中全局变量的位置无关,只与压入堆栈的顺序有关;这种全局变量的获取,应该也包含函数变量,这个目前只是猜测,后面用例子来验证。

    示例4
    Object manipulation
    源码

    // t = { foo: 42, bar: true }

    js_newobject(J);
    {
    js_pushnumber(J, 42);
    js_setproperty(J, -2, "foo");
    js_pushboolean(J, 1);
    js_setproperty(J, -2, "bar");
    }
    js_setglobal(J, "t");
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    扩展为可执行程序,代码如下
    object1.c

    #include <stdio.h>
    #include <mujs.h>

    struct T
    {
    int foo;
    unsigned char bar;
    };

    int main(void)
    {
    js_State *J = js_newstate(NULL, NULL, JS_STRICT);
    // t = {foo:42, bar:12};
    js_newobject(J);
    {
    js_pushnumber(J, 42);
    js_setproperty(J, -2, "foo");
    js_pushnumber(J, 12);
    js_setproperty(J, -2, "bar");
    }
    js_setglobal(J, "t");

    struct T t;
    js_getglobal(J, "t"); // 找到t并将object压栈
    js_getproperty(J, -1, "foo"); // 此时t在栈顶,得到foo后再将foo的值压栈
    js_getproperty(J, -2, "bar"); // 此时t已经下沉一次,所以idx为-2
    t.foo = js_tonumber(J, -2);
    t.bar = js_tonumber(J, -1);
    printf("t.foo:%d, t.bar:%d ", t.foo, t.bar);
    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    执行结果

    [root@bogon javascript]# gcc object1.c -lmujs -g -o object1
    [root@bogon javascript]# ./object1
    t.foo:42, t.bar:12
    1
    2
    3
    这里面难点是在于理解js_setproperty中的idx参数,例子中都是”-2”,这个值是如何确定的,官方的参考手册too simple了,根本没有解释,只能去啃源码。
    void js_setproperty(js_State *J, int idx, const char *name);
    下面用堆栈图来说明object的创建和引用步骤


    我们可以通过一个例子来验证,在创建对象时增加属性,经过了以下几个步骤:
    1、创建object,将object压入stack;
    2、压入属性,可能是number, string, boolean等等
    3、将属性与object关联(加入到object的property chain),丢弃该属性
    4、如果要继续添加属性,重复2,3步骤

    object2.c

    #include <stdio.h>
    #include <mujs.h>

    struct T
    {
    int foo;
    unsigned char bar;
    };

    int main(void)
    {
    js_State *J = js_newstate(NULL, NULL, JS_STRICT);
    js_dofile(J, "object.js");
    int i;
    js_pushnumber(J, 100);
    // t = {foo:42, bar:12};
    js_newobject(J);
    {
    i = js_tonumber(J, -2);
    printf("i:%d ", i);
    js_pushnumber(J, 42);
    js_setproperty(J, -2, "foo");
    i = js_tonumber(J, -2);
    printf("i:%d ", i);
    js_pushnumber(J, 12);
    js_setproperty(J, -2, "bar");
    }
    js_setglobal(J, "t");
    i = js_tonumber(J, -1);
    printf("i:%d ", i);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    执行结果

    [root@bogon javascript]# gcc object2.c -lmujs -g -o object2
    [root@bogon javascript]# ./object2
    i:100
    i:100
    i:100
    1
    2
    3
    4
    5
    三个地方打印的i都是100,都获取到了number的值,所以大家可以自己对照着看

    示例5
    Callbacks from C to JS (by name)

    static int call_callback(js_State *J, const char *arg1, int arg2)
    {
    int result;

    /* Find the function to call. */
    js_getglobal(J, "my_callback");

    /* Push arguments to function. */
    js_pushnull(J); /* the 'this' object to use */
    js_pushstring(J, arg1);
    js_pushnumber(J, arg2);

    /* Call function and check for exceptions. */
    if (js_pcall(J, 2)) {
    fprintf(stderr, "an exception occurred in the javascript callback ");
    js_pop(J, 1);
    return -1;
    }

    /* Retrieve return value. */
    result = js_tonumber(J, -1);
    js_pop(J, 1);

    return result;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    扩展为可执行程序
    callback1.c

    #include <stdio.h>
    #include <mujs.h>


    static void jsB_print(js_State *J)
    {
    int i, top = js_gettop(J);
    for (i = 1; i < top; ++i) {
    const char *s = js_tostring(J, i);
    if (i > 1) putchar(' ');
    fputs(s, stdout);
    }
    putchar(' ');
    js_pushundefined(J);
    }

    static int call_callback(js_State *J, const char *arg1, int arg2)
    {
    int result;

    /* Find the function to call. */
    js_getglobal(J, "my_callback");

    /* Push arguments to function. */
    js_pushnull(J); /* the 'this' object to use */
    js_pushstring(J, arg1);
    js_pushnumber(J, arg2);

    /* Call function and check for exceptions. */
    if (js_pcall(J, 2)) {
    fprintf(stderr, "an exception occurred in the javascript callback ");
    js_pop(J, 1);
    return -1;
    }

    /* Retrieve return value. */
    result = js_tonumber(J, -1);
    js_pop(J, 1);

    return result;
    }

    void main(void)
    {
    js_State * J = js_newstate(NULL, NULL, JS_STRICT);
    js_dofile(J, "callback.js");

    js_newcfunction(J, jsB_print, "print", 0);
    js_setglobal(J, "print");

    int ret = call_callback(J, "Hello world!", 100);

    printf("ret:%d ", ret);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    对应的callback.js脚本也很简单

    function my_callback(arg1, arg2)
    {
    print(arg1);
    return (arg2+2);
    }
    1
    2
    3
    4
    5
    6
    执行结果

    [root@bogon javascript]# gcc callback1.c -g -lmujs -o callback1
    [root@bogon javascript]# ./callback1
    Hello world!
    ret:102
    1
    2
    3
    4
    源码简单,注释也相对完整,功能不多说,还是画一下堆栈图,这样就比较清楚,在这之前,还是用之前压入一个number值来测试不同阶段number值的位置来看看,整个过程做了哪些操作。

    callback2.c

    #include <stdio.h>
    #include <mujs.h>


    static void jsB_print(js_State *J)
    {
    int i, top = js_gettop(J);
    for (i = 1; i < top; ++i) {
    const char *s = js_tostring(J, i);
    if (i > 1) putchar(' ');
    fputs(s, stdout);
    }
    putchar(' ');
    js_pushundefined(J);
    }
    static int call_callback(js_State *J, const char *arg1, int arg2)
    {
    int result;
    int i;
    js_pushnumber(J, 100);

    /* Find the function to call. */
    js_getglobal(J, "my_callback");

    i = js_tonumber(J, -2); // 1
    printf("i:%d ", i);

    /* Push arguments to function. */
    js_pushnull(J); /* the 'this' object to use */
    js_pushstring(J, arg1);
    js_pushnumber(J, arg2);

    i = js_tonumber(J, -5); // 2
    printf("i:%d ", i);

    /* Call function and check for exceptions. */
    if (js_pcall(J, 2)) {
    fprintf(stderr, "an exception occurred in the javascript callback ");
    js_pop(J, 1);
    return -1;
    }

    i = js_tonumber(J, -2); // 3
    printf("i:%d ", i);

    /* Retrieve return value. */
    result = js_tonumber(J, -1);
    js_pop(J, 1);

    i = js_tonumber(J, -1); // 4
    printf("i:%d ", i);
    return result;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    执行结果

    [root@bogon javascript]# ./callback2
    i:100
    i:100
    Hello world!
    i:100
    i:100
    ret:102
    1
    2
    3
    4
    5
    6
    7


    说明:
    1. 函数调用都是围绕着stack的压栈和出栈的操作,在函数callback之后,要清空使用记录,恢复到调用前的状态。
    2. 例子中还借用了mujs开源包main.c中的代码,实现了js脚本的print功能,支持终端输出。我们知道javascript主要是web开发,所以在标准输入输出,文本操作方面支持的不好,mujs考虑到这点,在main.c举例增加了相关函数,使得javascript可以调用这些功能函数,但这样一来javascript就不是标准的版本,必须在mujs解释器下执行,如果更换其他解释器,那么这些函数需要调整。

    示例6
    Callbacks from C to JS

    const char *handle = NULL; /* handle to stowed away js function */

    static void set_callback(js_State *J)
    {
    if (handle)
    js_unref(J, handle); /* delete old function */
    js_copy(J, 1);
    handle = js_ref(J); /* stow the js function in the registry */
    }

    static void call_callback(js_State *J, int arg1, int arg2)
    {
    js_getregistry(J, handle); /* retrieve the js function from the registry */
    js_pushnull(J);
    js_pushnumber(J, arg1);
    js_pushnumber(J, arg2);
    js_pcall(J, 2);
    js_pop(J, 1);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    这个例子没有看懂,后续解决。

    示例7
    Complete userdata example
    源码比较长

    #include <stdio.h>
    #include <mujs.h>

    #define TAG "File"

    static void new_File(js_State *J)
    {
    FILE *file;

    if (js_isundefined(J, 1)) {
    file = stdin;
    } else {
    const char *filename = js_tostring(J, 1);
    file = fopen(filename, "r");
    if (!file)
    js_error(J, "cannot open file: '%s'", filename);
    }

    js_currentfunction(J);
    js_getproperty(J, -1, "prototype");
    js_newuserdata(J, TAG, file);
    }

    static void File_prototype_readByte(js_State *J)
    {
    FILE *file = js_touserdata(J, 0, TAG);
    js_pushnumber(J, getc(file));
    }

    static void File_prototype_readLine(js_State *J)
    {
    char line[256], *s;
    FILE *file = js_touserdata(J, 0, TAG);
    s = fgets(line, sizeof line, file);
    if (s)
    js_pushstring(J, line);
    else
    js_pushnull(J);
    }

    static void File_prototype_close(js_State *J)
    {
    FILE *file = js_touserdata(J, 0, TAG);
    fclose(file);
    js_pushundefined(J);
    }

    void initfile(js_State *J)
    {
    js_getglobal(J, "Object");
    js_getproperty(J, -1, "prototype"); // File.prototype.[[Prototype]] = Object.prototype
    js_newuserdata(J, TAG, stdin); // File.prototype.[[Userdata]] = stdin
    {
    js_newcfunction(J, File_prototype_readByte, "File.prototype.readByte", 0);
    js_defproperty(J, -2, "readByte", JS_DONTENUM);

    js_newcfunction(J, File_prototype_readLine, "File.prototype.readLine", 0);
    js_defproperty(J, -2, "readLine", JS_DONTENUM);

    js_newcfunction(J, File_prototype_close, "File.prototype.close", 0);
    js_defproperty(J, -2, "close", JS_DONTENUM);
    }
    js_newcconstructor(J, new_File, new_File, "File", 1);
    js_defglobal(J, "File", JS_DONTENUM);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    待续….
    这个例子,也没看懂~
    ————————————————
    版权声明:本文为CSDN博主「炼气士」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/ljd680/article/details/79423284

  • 相关阅读:
    java反射
    2018 Multi-University Training Contest 4 Problem B. Harvest of Apples 【莫队+排列组合+逆元预处理技巧】
    逆元小结
    2018 Multi-University Training Contest 1 Distinct Values 【贪心 + set】
    Codeforces Round #533 (Div. 2) C. Ayoub and Lost Array 【dp】
    Codeforces Round #533 (Div. 2) B. Zuhair and Strings 【模拟】
    2018 Multi-University Training Contest 3 Problem F. Grab The Tree 【YY+BFS】
    ZOJ Monthly, January 2019 Little Sub and his Geometry Problem 【推导 + 双指针】
    ZOJ Monthly, January 2019 Little Sub and Isomorphism Sequences 【离线离散化 + set + multiset】
    EOJ Monthly 2019.1 唐纳德先生与这真的是签到题吗 【数学+暴力+multiset】
  • 原文地址:https://www.cnblogs.com/yasepix/p/12337905.html
Copyright © 2020-2023  润新知