You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

114 lines
4.7 KiB

=proto
int duk_safe_call(duk_context *ctx, duk_safe_call_function func, int nargs, int nrets, int errhandler_index);
=stack
[ ... arg1! ...! argN! ] -> [ ... ret1! ...! retN! ]
=summary
<p>Perform a protected pure C function call inside the current value stack frame
(the call is not visible on the call stack). <code>nargs</code> topmost values in the
current value stack frame are identified as call arguments, and <code>nrets</code>
return values are provided after the call returns. <code>errhandler_index</code> points
to an error handler function in the current stack frame (below call arguments) which
can modify an error value before it is thrown; to use the default error handler,
set <code>errhandler_index</code> to <code>DUK_INVALID_INDEX</code>.</p>
<p>The return value is:</p>
<ul>
<li><code>DUK_EXEC_SUCCESS</code> (0): call succeeded, <code>nargs</code> arguments are replaced
with <code>nrets</code> return values. (This return code constant is guaranteed to be
zero, so that one can check for success with a "zero or non-zero" check.)</li>
<li><code>DUK_EXEC_ERROR</code>: call failed, <code>nargs</code> arguments are replaced with
<code>nrets</code> values, first of which is an error value and the rest are <code>undefined</code>.
(In exceptional cases, e.g. when there are too few arguments on the value stack, the call
returns non-zero but may leave the stack in an inconsistent state.)</li>
</ul>
<div class="note">
Unlike most Duktape API calls, this call returns zero on success. This allows
multiple error codes to be defined later.
</div>
<p>Because this call operates on the current value stack frame, stack behavior
differs a bit from other call types. Although the target function signature
matches Duktape/C functions, value stack and return code policies are different.</p>
<p>The top <code>nargs</code> elements of the stack top are identified as arguments to
<code>func</code> establishing a "base index" for the return stack as:</p>
<pre>
(duk_get_top() - nargs)
</pre>
<p>When <code>func</code> returns, it indicates with its return value the number of
return values it has pushed on top of the stack; multiple or zero return
values possible. The stack is then manipulated so that there are exactly
<code>nrets</code> values starting at the "base index" established before the call.</p>
<p>Note that since <code>func</code> has full access to the value stack, it may modify
the stack below the indended arguments and even pop elements below the "base index"
off the stack. Such elements are restored with <code>undefined</code> values before
returning, to ensure that the stack is always in a consistent state upon returning.</p>
<p>If an error occurs, the stack will still have <code>nrets</code> values at "base index";
the first of such values is the error, and the remaining values are <code>undefined</code>.
If <code>nrets</code> is zero, the error will not be present on the stack (the return stack
top will equal the "base index"), so calling this function with <code>nrets</code> as 0
is not very useful.</p>
<p>Example with <code>nargs = 3</code>, <code>nrets = 2</code>, <code>func</code> returns 4.
Pipe chars indicate logical boundaries:</p>
<pre>
.--- frame bottom
|
| .--- "base index"
v v
[ ... | ... | a b c ] stack before calling 'func'
[ ... | ... | a b | x y z w ] stack after calling 'func', which has
popped one argument and written four
return values (and returned 4)
[ ... | ... | x y ] stack after duk_safe_call() returns,
2 (= nrets) first 'func' return values
are left at "base index"
</pre>
<div class="note">
Note that <code>func</code> uses caller stack frame, so bottom-based references
are dangerous within 'func'.
</div>
=example
int my_func(duk_context *ctx) {
double a, b, c;
a = duk_get_number(ctx, -3);
b = duk_get_number(ctx, -2);
c = duk_get_number(ctx, -1);
duk_push_number(ctx, a + b);
/* Indicates that there is only one return value. Because the caller
* requested two (nrets == 2), Duktape will automatically add an
* additional "undefined" result value.
*/
return 1;
}
duk_push_int(ctx, 10);
duk_push_int(ctx, 11);
duk_push_int(ctx, 12);
rc = duk_safe_call(ctx, my_func, 3 /*nargs*/, 2 /*nrets*/, DUK_INVALID_INDEX);
if (rc == DUK_EXEC_SUCCESS) {
printf("1st return value: %s\n", duk_to_string(ctx, -2)); /* 21 */
printf("2nd return value: %s\n", duk_to_string(ctx, -1)); /* undefined */
} else {
printf("error value: %s\n", duk_to_string(ctx, -2));
}
duk_pop_2(ctx);
=tags
call
=fixme
Error handler model to be cleaned up.