Skip to content

12. Call a C function from the JS side

Gurigraphics edited this page Mar 24, 2022 · 1 revision

Create file

Create file: jseval.c

/* jseval.c */
#include <stdio.h>
#include <string.h>

#include <quickjs.h>

JSValue jsFprint(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv, FILE *f) {
  for (int i = 0; i < argc; ++i) {
    if (i != 0) {
      fputc(' ', f);
    }
    const char *str = JS_ToCString(ctx, argv[i]);
    if (!str) {
      return JS_EXCEPTION;
    }
    fputs(str, f);
    JS_FreeCString(ctx, str);
  }
  fputc('\n', f);
  return JS_UNDEFINED;
}

JSValue jsPrint(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) {
  return jsFprint(ctx, jsThis, argc, argv, stdout);
}

JSValue jsPrintErr(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv) {
  return jsFprint(ctx, jsThis, argc, argv, stderr);
}

void initContext(JSContext *ctx) {
  JSValue global = JS_GetGlobalObject(ctx);

  //Add console to globalThis
  JSValue console = JS_NewObject(ctx);
  JS_SetPropertyStr(ctx, global, "console", console);
  // console.set log
  JS_SetPropertyStr(ctx, console, "log", JS_NewCFunction(ctx, jsPrint, "log", 1));
  // console.Set error 
  JS_SetPropertyStr(ctx, console, "error", JS_NewCFunction(ctx, jsPrintErr, "error", 1));

  JS_FreeValue(ctx, global);
}

int main(int argc, char const *argv[]) {
  int exitCode = 0;

  JSRuntime *rt = JS_NewRuntime();
  JSContext *ctx = JS_NewContext(rt);

  initContext(ctx);

  for (int i = 1; i < argc; ++i) {
    JSValue ret = JS_Eval(ctx, argv[i], strlen(argv[i]), "<input>", JS_EVAL_FLAG_STRICT);
    if (JS_IsException(ret)) {
      JSValue e = JS_GetException(ctx);
      jsPrintErr(ctx, JS_NULL, 1, &e);
      JS_FreeValue(ctx, e);
      exitCode = 1;
      break;
    } else if (JS_IsUndefined(ret)) {
      // nop
    } else {
      jsPrint(ctx, JS_NULL, 1, &ret);
    }
    JS_FreeValue(ctx, ret);
  }

  JS_FreeContext(ctx);
  JS_FreeRuntime(rt);
  return exitCode;
}

/*
gcc -c -Os -Wall -I./quickjs/include jseval.c
gcc -Wl,-s -L./quickjs/lib jseval.o -l quickjs -l m -o jseval 
*/ 

Insert in project the quickjs folder files

quickjs/include
- cutils.h | 8kb
- quickjs.h | 42kb
- quickjs-libc.h | 3kb

quickjs/lib
- libquickjs.a | 6073kb

Compile

Create jseval.o

gcc -c -Os -Wall -I./quickjs/include jseval.c

Create jseval.exe

gcc -Wl,-s -L./quickjs/lib jseval.o -l quickjs -l m -o jseval

Run

jseval.exe "3*3"
#Result: 
#9

jseval.exe "[1,2,3].map(x => x*10).forEach( x => console.log(x) )"
#Result:
#10
#20
#30

References

https://linuxtut.com/en/16cdbc69d4fd4a3dccbf/

Clone this wiki locally