Getting started

Downloading

Download the source distributable from the Download page.

Command line tool

Unpack the distributable:

$ cd /tmp
$ tar xvfJ duktape-<version>.tar.xz

Compile the command line tool using the provided Makefile:

$ cd /tmp/duktape-<version>/
$ make -f Makefile.cmdline
The Makefile assumes you have gcc installed. If you don't, you can just edit the Makefile to match your compiler (the Makefile is quite simple).
The command line tool avoids platform dependencies by default. If you're running a UNIX variant and have readline and the necessary development headers, you can enable line editing support by editing the Makefile:

You can now run Ecmascript code interactively:

$ ./duk
((o) Duktape [no readline] 1.1.0 (v1.1.0)
duk> print('Hello world!')
Hello world!
= undefined

You can also run Ecmascript code from a file which is useful for playing with features and algorithms. As an example, create fib.js:



Test the script from the command line:

$ ./duk fib.js
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181

Integrating Duktape into your program

The command line tool is simply an example of a program which embeds Duktape. Embedding Duktape into your program is very simple: just add duktape.c and duktape.h to your build, and call the Duktape API from elsewhere in your program.

The distributable contains a very simple example program, hello.c, which illustrates this process. Compile the test program e.g. as (see Compiling for compiler option suggestions):

$ cd /tmp/duktape-<version>/
$ gcc -std=c99 -o hello -Isrc/ src/duktape.c examples/hello/hello.c -lm

The test program creates a Duktape context and uses it to run some Ecmascript code:

$ ./hello
Hello world!
2+3=5

Because Duktape is an embeddable engine, you don't need to change the basic control flow of your program. The basic approach is:

Let's look at a simple example program. The program reads in a line from stdin using a C mainloop, calls an Ecmascript helper to transform the line, and prints out the result. The line processing function can take advantage of Ecmascript goodies like regular expressions, and can be easily modified without recompiling the C program.

The script code will be placed in process.js. The example line processing function converts a plain text line into HTML, and automatically bolds text between stars:



The C code, processlines.c initializes a Duktape context, evaluates the script, then proceeds to process lines from stdin, calling processLine() for every line:



Let's look at the Duktape specific parts of the example code piece by piece. Here we need to gloss over some details for brevity, see Programming model for a detailed discussion:

Compile like above:

$ gcc -std=c99 -o processlines -Isrc/ src/duktape.c processlines.c -lm

Test run (ensure that process.js is in the current directory):

$ echo "I like *Sam & Max*." | ./processlines
I like <b>Sam &#38; Max</b>.

Calling C code from Ecmascript (Duktape/C bindings)

The integration example illustrated how C code can call into Ecmascript to do things which are easy in Ecmascript but difficult in C.

Ecmascript also often needs to call into C when the situation is reversed. For instance, while scripting is useful for many things, it is not optimal for low level byte or character processing. Being able to call optimized C helpers allows you to write most of your script logic in nice Ecmascript but call into C for the performance critical parts. Another reason for using native functions is to provide access to native libraries.

To implement a native function you write an ordinary C function which conforms to a special calling convention, the Duktape/C binding. Duktape/C functions take a single argument, a Duktape context, and return a single value indicating either error or number of return values. The function accesses call arguments and places return values through the Duktape context's value stack, manipulated with the Duktape API. We'll go deeper into Duktape/C binding and the Duktape API later on. Example:

duk_ret_t my_native_func(duk_context *ctx) {
    double arg = duk_require_number(ctx, 0 /*index*/);
    duk_push_number(ctx, arg * arg);
    return 1;
}

Let's look at this example line by line:

We'll use a primality test as an example for using native code to speed up Ecmascript algorithms. More specifically, our test program searches for primes under 1000000 which end with the digits '9999'. The Ecmascript version of the program is:



Note that the program uses the native helper if it's available but falls back to an Ecmascript version if it's not. This allows the Ecmascript code to be used in other containing programs. Also, if the prime check program is ported to another platform where the native version does not compile without changes, the program remains functional (though slower) until the helper is ported. In this case the native helper detection happens when the script is loaded. You can also detect it when the code is actually called which is more flexible.

A native helper with functionality equivalent to primeCheckEcmascript is quite straightforward to implement. Adding a program main we get primecheck.c:



The new calls here are, line by line:

Compile like above:

$ gcc -std=c99 -o primecheck -Isrc/ src/duktape.c primecheck.c -lm

Test run (ensure that prime.js is in the current directory):

$ time ./primecheck
Have native helper: true
49999 59999 79999 139999 179999 199999 239999 289999 329999 379999 389999
409999 419999 529999 599999 619999 659999 679999 769999 799999 839999 989999

real	0m2.985s
user	0m2.976s
sys	0m0.000s

Because most execution time is spent in the prime check, the speed-up compared to plain Ecmascript is significant. You can check this by editing prime.js and disabling the use of the native helper:

// Select available helper at load time
var primeCheckHelper = primeCheckEcmascript;

Re-compiling and re-running the test:

$ time ./primecheck
Have native helper: false
49999 59999 79999 139999 179999 199999 239999 289999 329999 379999 389999
409999 419999 529999 599999 619999 659999 679999 769999 799999 839999 989999

real	0m23.609s
user	0m23.573s
sys	0m0.000s