Итак, в основном у меня есть длинный массив объектов, и мне нужно несколько раз вызвать функцию JavaScript с массивом в качестве параметра. Я уже работал, когда воссоздаю список каждый раз, когда вызываю функцию, но попытка переместить массив на вершину стека Duktape не сработала, как ожидалось. Может быть, я нахожусь на совершенно неправильном пути …
duk_context* ctx(duk_create_heap_default());
duk_push_c_function(ctx, nativePrint, DUK_VARARGS);
duk_put_global_string(ctx, "print");
/// Define the function the first time
duk_eval_string(ctx, "function func(entries, targetEntry) { print(targetEntry, JSON.stringify(entries)); return 404; }");
duk_get_global_string(ctx, "func");
/// Define lambdas to create the array
auto pushObject = [&] () {
duk_idx_t obj_idx;
obj_idx = duk_push_object(ctx);
duk_push_int(ctx, 42);
duk_put_prop_string(ctx, obj_idx, "meaningOfLife");
};
auto pushArray = [&] () {
duk_idx_t arr_idx;
arr_idx = duk_push_array(ctx);
pushObject();
duk_put_prop_index(ctx, arr_idx, 0);
pushObject();
duk_put_prop_index(ctx, arr_idx, 1);
return arr_idx;
};
/// Push the arguments
auto arr_idx = pushArray();
duk_push_number(ctx, 102);
/// Define lambda to call the function
auto processEntry = [&] () {
if (duk_pcall(ctx, 2 /*nargs*/) != 0) {
printf("Error: %s\n", duk_safe_to_string(ctx, -1));
} else {
if (duk_is_number(ctx, -1)) cout << "NumRes: " << duk_get_number(ctx, -1) << endl;
else printf("Res: %s\n", duk_safe_to_string(ctx, -1));
}
duk_pop(ctx);
cout << endl;
};
/// Calling the function the first time
processEntry();
/// Loading the function as the global string again
duk_eval_string(ctx, "function func(entries, targetEntry) { print(targetEntry, JSON.stringify(entries)); return 404; }");
duk_get_global_string(ctx, "func");
/// Attempt to move the array to the top and execute the function
/// Executing pushArray(); again works but not duk_swap_top(...);
// pushArray();
duk_swap_top(ctx, arr_idx);
duk_push_number(ctx, 444);
processEntry();
Как видите, в самом низу я пытаюсь позвонить duk_swap_top(ctx, arr_idx)
для того, чтобы переместить массив наверх. Видимо, он не делает то, что я думал, а вместо этого возвращает TypeError: undefined not callable
. При замене этого другим pushArray();
это работает, как ожидалось, и оба 102 а также 444 распечатывается.
Мне кажется, что вы помещаете массив и ‘102’ в стек значений:
[ ... array 102 ]
Затем вы вызываете duk_pcall (), которая использует аргументы (nargs = 2) и отправляет результат:
[ ... result ]
Результат тогда выскочил. После вызова массив больше не находится в стеке значений.
Существуют различные способы структурирования вашего кода, но вы можете сначала зарегистрировать ‘func’ и создать массив, а затем использовать следующую последовательность для каждого вызова (включая первый):
duk_get_global_string(ctx, "func");
duk_dup(ctx, arr_idx); /* duplicate array reference */
duk_push_uint(ctx, 1234); /* additional argument, varies? */
rc = duk_pcall(ctx, 2);
/* inspect result */
duk_pop(ctx);
Это сохраняет массив в arr_idx между вызовами.
Других решений пока нет …