Browse Source

breakdown parts into guide gettingstarted

pull/1/head
Sami Vaarala 11 years ago
parent
commit
6e641204f4
  1. 4
      examples/gettingstarted/processlines.c
  2. 133
      website/guide/gettingstarted.html
  3. 19
      website/style-content.css

4
examples/gettingstarted/processlines.c

@ -25,9 +25,9 @@ int main(int argc, const char *argv[]) {
line[idx++] = '\0';
duk_push_global_object(ctx);
duk_get_prop_string(ctx, -1, "processLine");
duk_get_prop_string(ctx, -1 /*index*/, "processLine");
duk_push_string(ctx, line);
duk_call(ctx, 1);
duk_call(ctx, 1 /*nargs*/);
printf("%s\n", duk_to_string(ctx, -1));
duk_pop(ctx);

133
website/guide/gettingstarted.html

@ -161,9 +161,9 @@ int main(int argc, const char *argv[]) {
line[idx++] = '\0';
duk_push_global_object(ctx);
duk_get_prop_string(ctx, -1, "processLine");
duk_get_prop_string(ctx, -1 /*index*/, "processLine");
duk_push_string(ctx, line);
duk_call(ctx, 1);
duk_call(ctx, 1 /*nargs*/);
printf("%s\n", duk_to_string(ctx, -1));
duk_pop(ctx);
@ -181,6 +181,97 @@ int main(int argc, const char *argv[]) {
}
</pre>
<p>Let's look at the Duktape specific parts of the example code line by line.
Here we need to gloss over some details for brevity, see
<a href="#programming">Programming model</a> for a detailed discussion:</p>
<ul class="breakdown"> <!-- breakdown -->
<li>
<pre>
ctx = duk_create_heap_default();
if (!ctx) { exit(1); }
</pre>
<p>First we create a Duktape context. A context allows us to exchange values
with Ecmascript code by pushing and popping values to the <b>value stack</b>.
Most calls in the Duktape API operate with the value stack, pushing, popping,
and examining values on the stack.</p>
</li>
<li>
<pre>
duk_eval_file(ctx, "process.js");
duk_pop(ctx); /* pop eval result */
</pre>
<p>The first call reads in <tt>process.js</tt> and evaluates its contents.
The script registers the <tt>processLine()</tt> function into the Ecmascript
global object. The result of the evaluation is pushed on top of the value
stack. Here we don't need the evaluation result, so we pop the value off
the stack.</p>
</li>
<li>
<pre>
duk_push_global_object(ctx);
duk_get_prop_string(ctx, -1 /*index*/, "processLine");
</pre>
<p>The first call pushes the Ecmascript global object to the value stack.
The second call looks up <tt>processLine</tt> property of the global object.
The script in <tt>process.js</tt> has registered a callback function into
the global object with this name. The <tt>-1</tt> argument is an index to
the value stack; negative values refer to stack elements starting from the
top, so <tt>-1</tt> refers to the topmost element of the stack, the property
lookup result.</p>
</li>
<li>
<pre>
duk_push_string(ctx, line);
</pre>
<p>Pushes the string pointed to by <tt>line</tt> to the value stack. The
string length is automatically determined by scanning for a NUL terminator
(same as <tt>strlen()</tt>). Duktape makes a copy of the string when it is
pushed to the stack, so the <tt>line</tt> buffer can be freely modified when
the call returns.</p>
</li>
<li>
<pre>
duk_call(ctx, 1 /*nargs*/);
</pre>
<p>At this point the value stack contains: the global object, the processLine
function, and the <tt>line</tt> string. This line calls an Ecmascript function
with the specified number of arguments; here the argument count is 1. The
target function is expected to reside just before the argument list on the
value stack. After the API call returns, the arguments have been replaced with
a single return value, so the stack contains: the global object and the call
result.</p>
</li>
<li>
<pre>
printf("%s\n", duk_to_string(ctx, -1));
duk_pop(ctx);
</pre>
<p>The <tt>duk_to_string()</tt> call requests Duktape to convert the value stack
element at index -1 (the topmost value on the stack, which is the processLine
function call result here) to a string, returning a <tt>const char *</tt> pointing
to the result. This return value is a read-only, NUL terminated UTF-8 value which
C code can use directly. Here we just print out the string. After we've printed
the string, we pop the value off the value stack.</p>
</li>
<li>
<pre>
duk_destroy_heap(ctx);
</pre>
<p>Destroy the Duktape context, freeing all resources held by the context.
In our example we left the global object on the value stack on purpose.
This call will free the value stack and all references on the value stack.
No memory leaks will occur even if the value stack is not empty.</p>
</li>
</ul> <!-- breakdown -->
<p>Compile like above:</p>
<pre>
$ gcc -o processlines -Isrc/ src/duktape.c processlines.c -lm
@ -214,12 +305,44 @@ accesses call arguments and places return values through the Duktape context's
Duktape/C binding and the Duktape API later on. Example:</p>
<pre class="c-code">
int my_native_func(duk_context *ctx) {
double arg = duk_require_number(ctx, 0 /*index*/); /* read 1st arg */
duk_push_number(ctx, arg * arg); /* push arg^2 */
return 1; /* return value on top of stack, i.e. arg^2 */
double arg = duk_require_number(ctx, 0 /*index*/);
duk_push_number(ctx, arg * arg);
return 1;
}
</pre>
<p>Let's look at this example line by line:</p>
<ul class="breakdown"> <!-- breakdown -->
<li>
<pre>
double arg = duk_require_number(ctx, 0 /*index*/);
</pre>
<p>Check that the number at value stack index 0 (bottom of the stack, first
argument to function call) is a number; if not, throws an error and never
returns. If the value is a number, return it as a <tt>double</tt>.</p>
</li>
<li>
<pre>
duk_push_number(ctx, arg * arg);
</pre>
<p>Compute square of argument and push it to the value stack.</p>
</li>
<li>
<pre>
return 1;
</pre>
<p>Return from the function call, indicating that there is a (single) return
value on top of the value stack. You could also return <tt>0</tt> to indicate
that no return value is given (in which case Duktape defaults to Ecmascript
<tt>undefined</tt>). A negative return value which causes an error to be
automatically thrown: this is a shorthand for throwing errors conveniently.
See <a href="#programming">Programming model</a> for more details.</li>
</ul> <!-- breakdown -->
<p>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

19
website/style-content.css

@ -122,6 +122,25 @@ ul.taglist li {
}
}
/* special styling for breakdowns (additive to base ul / ul li style) */
ul.breakdown {
margin: 2ex 0 2ex 2em; /* additional indent */
}
ul.breakdown li {
list-style: none;
padding: 0.5ex 2ex 1ex 2ex;
/*background: #f8f8f8;*/
border: 2px solid #eeeeee;
border-radius: 10px;
margin: 1ex 0 1ex 0;
}
@media screen and (max-width:800px) {
ul.breakdown {
margin: 2ex 0 2ex 0; /* remove indent */
}
}
.content pre {
overflow: auto;
font-family: monospace;

Loading…
Cancel
Save