mirror of https://github.com/svaarala/duktape.git
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.
141 lines
5.7 KiB
141 lines
5.7 KiB
name: duk_safe_call
|
|
|
|
proto: |
|
|
duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, void *udata, duk_idx_t nargs, duk_idx_t nrets);
|
|
|
|
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. Calling code must ensure value stack has reserve for <code>nrets</code>
|
|
using e.g. <code><a href="#duk_check_stack">duk_check_stack()</a></code>, and
|
|
handling reservation errors.</p>
|
|
|
|
<p>The <code>udata</code> (userdata) pointer is passed on to
|
|
<code>func</code> as is, and makes it easy to pass one or more C values to
|
|
the target function without using the value stack. Multiple values can be
|
|
passed by packing them into a stack-allocated C struct and passing a pointer
|
|
to the struct as userdata. The userdata argument is not interpreted by
|
|
Duktape; if it isn't needed simply pass a <code>NULL</code> and ignore the
|
|
udata argument in the safe call target.</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
|
|
may throw.)</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
|
|
and return code handling differ a bit from other call types.</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 value stack behavior with <code>nargs = 3</code>, <code>nrets = 2</code>,
|
|
<code>func</code> returns 4. Pipe chars indicate logical value stack 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 the caller's stack frame, so bottom-based
|
|
references are dangerous within 'func' unless the calling context is known.
|
|
</div>
|
|
|
|
<div class="note">
|
|
The userdata argument was added in Duktape 2.x.
|
|
</div>
|
|
|
|
example: |
|
|
typedef struct {
|
|
int floor;
|
|
} my_safe_args;
|
|
|
|
duk_ret_t my_safe_func(duk_context *ctx, void *udata) {
|
|
my_safe_args *args = (my_safe_args *) udata;
|
|
double a, b, c, t;
|
|
|
|
a = duk_get_number(ctx, -3);
|
|
b = duk_get_number(ctx, -2);
|
|
c = duk_get_number(ctx, -1); /* ignored on purpose */
|
|
t = a + b;
|
|
if (args->floor) {
|
|
t = floor(t);
|
|
}
|
|
duk_push_number(ctx, t);
|
|
|
|
/* 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;
|
|
}
|
|
|
|
my_safe_args args; /* C struct whose pointer is passed as userdata */
|
|
duk_int_t rc;
|
|
|
|
args.floor = 1;
|
|
duk_push_int(ctx, 10);
|
|
duk_push_int(ctx, 11);
|
|
duk_push_int(ctx, 12);
|
|
rc = duk_safe_call(ctx, my_func, (void *) &args, 3 /*nargs*/, 2 /*nrets*/);
|
|
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
|
|
- protected
|
|
|
|
# Introduced in 1.0.0 but incompatible change in 2.0.0.
|
|
introduced: 1.0.0
|
|
|