---
title: C + QuickJS
pagination_prev: demos/bigdata/index
pagination_next: solutions/input
---

import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';

QuickJS is an embeddable JS engine written in C.  It provides a separate set of
functions for interacting with the filesystem and the global object.  It can run
the standalone browser scripts.

The [Standalone scripts](/docs/getting-started/installation/standalone) can be
parsed and evaluated in a QuickJS context.

## Integration Details

_Initialize QuickJS_

QuickJS provides a `global` object through `JS_GetGlobalObject`:

```c
/* initialize */
JSRuntime *rt = JS_NewRuntime();
JSContext *ctx = JS_NewContext(rt);

/* obtain reference to global object */
JSValue global = JS_GetGlobalObject(ctx);

/* DO WORK HERE */

/* free after use */
JS_FreeValue(ctx, global);

/* cleanup */
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
```

:::warning

All values must be freed with `JS_FreeValue` before calling `JS_FreeContext`!

`JS_IsException` should be used for validation.

Cleanup and validation code is omitted from the discussion.  The integration
example shows structured validation and controlled memory usage.

:::

_Load SheetJS Scripts_

The main library can be loaded by reading the script from the file system and
evaluating in the QuickJS context:

```c
static char *read_file(const char *filename, size_t *sz) {
  FILE *f = fopen(filename, "rb");
  if(!f) return NULL;
  long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f); fsee  (f, 0, SEEK_SET); }
  char *buf = (char *)malloc(fsize * sizeof(char));
  *sz = fread((void *) buf, 1, fsize, f);
  fclose(f);
  return buf;
}

// ...
  /* load library */
  {
    size_t len; char *buf = read_file("xlsx.full.min.js", &len);
    JS_Eval(ctx, buf, len, "<input>", 0);
    free(buf);
  }
```

To confirm the library is loaded, `XLSX.version` can be inspected:

```c
/* obtain reference to the XLSX object */
JSValue XLSX = JS_GetPropertyStr(ctx, global, "XLSX");

/* print version */
JSValue version = JS_GetPropertyStr(ctx, XLSX, "version");
size_t vlen; const char *vers = JS_ToCStringLen(ctx, &vlen, version);
printf("Version: %s\n", vers);
```

### Reading Files

`JS_NewArrayBuffer` can generate an `ArrayBuffer` from a C byte array. The
function signature expects `uint8_t *` instead of `char *`:

```c
/* read file */
size_t dlen; uint8_t * dbuf = (uint8_t *)read_file("pres.numbers", &dlen);

/* load data into array buffer */
JSValue ab = JS_NewArrayBuffer(ctx, dbuf, dlen, NULL, NULL, 0);

/* obtain reference to the XLSX object */
JSValue XLSX = JS_GetPropertyStr(ctx, global, "XLSX");

/* call XLSX.read(ab) */
JSValue XLSX_read = JS_GetPropertyStr(ctx, XLSX, "read");
JSValue args[] = { ab };
JSValue wb = JS_Call(ctx, XLSX_read, XLSX, 1, args);
```

## Complete Example

The "Integration Example" covers a traditional integration in a C application,
while the "CLI Test" demonstrates other concepts using the `quickjs` CLI tool.

### Integration Example

:::note

This demo was last tested on 2023 March 11 against QuickJS commit `2788d71` on
a Intel Mac. `gcc -v` printed:

```
Apple clang version 14.0.0 (clang-1400.0.29.202)
Target: x86_64-apple-darwin21.6.0
```

:::

0) Build `libquickjs.a`:

```bash
git clone https://github.com/bellard/quickjs
cd quickjs
git checkout 2788d71
make
cd ..
```

1) Copy `libquickjs.a` and `quickjs.h` into the working directory:

```bash
cp quickjs/libquickjs.a .
cp quickjs/quickjs.h .
```

2) Download [`sheetjs.quick.c`](pathname:///quickjs/sheetjs.quick.c):

```bash
curl -LO https://docs.sheetjs.com/quickjs/sheetjs.quick.c
```

3) Build the sample application:

```bash
gcc -o sheetjs.quick -Wall -lm libquickjs.a sheetjs.quick.c
```

This program tries to parse the file specified by the first argument

4) Download the standalone script and test file:

<ul>
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li>
<li><a href="https://sheetjs.com/pres.numbers">pres.numbers</a></li>
</ul>

<CodeBlock language="bash">{`\
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://sheetjs.com/pres.numbers`}
</CodeBlock>

5) Run the test program:

```
./sheetjs.quick pres.numbers
```

If successful, the program will print the library version number, file size,
first worksheet name, and the contents of the first sheet as CSV rows.


### CLI Test

:::note

This demo was last tested on 2023 March 11 against QuickJS `2021-03-27`.

:::

0) Ensure `quickjs` command line utility is installed

1) Download the standalone script and the test file:

<ul>
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li>
<li><a href="https://sheetjs.com/pres.numbers">pres.numbers</a></li>
</ul>

<CodeBlock language="bash">{`\
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://sheetjs.com/pres.numbers`}
</CodeBlock>

2) Download [`SheetJSQuick.js`](pathname:///quickjs/SheetJSQuick.js)

```bash
curl -LO https://docs.sheetjs.com/quickjs/SheetJSQuick.js
```

3) Test the program:

```bash
quickjs SheetJSQuick.js
```

If successful, the script will generate `SheetJSQuick.xlsx`.