Duktape получить значение массива
Я могу вставить массив со значениями по ключу в глобальном, как это:
duk_push_global_object(ctx);
duk_idx_t arr_idx = duk_push_array(ctx);
duk_push_string(ctx, "string by key");
duk_put_prop_string(ctx, arr_idx, "key");
duk_put_prop_string(ctx, -2, "global_array");
duk_pop(ctx);
но как я могу получить значение по ключу от глобального позже?
PS: простите за мой английский.
2 ответа
Код C, который вы разместили, эквивалентен следующему Javascript (это правильно?):
var t = []; // not actually registered into global object
t.key = 'string by key';
global_array = t;
Чтобы прочитать обратно global_array.key:
duk_get_global_string(ctx, "global_array");
duk_get_prop_string(ctx, -1, "key");
/* ... use the value, then pop it */
duk_pop(ctx); /* pop global_array */
Кстати, вы можете упростить код в вашем вопросе следующим образом:
duk_idx_t arr_idx = duk_push_array(ctx);
duk_push_string(ctx, "string by key");
duk_put_prop_string(ctx, arr_idx, "key");
duk_put_global_string(ctx, -2, "global_array");
Мне потребовалось очень много времени, чтобы понять, как это работает. Документы и примеры могут сбивать с толку, когда дело доходит до индексов стека Duktape, а также выдвигать и выталкивать вещи. Позвольте мне попытаться представить все это организованно, по частям, с дополнительным интервалом, чтобы было понятнее. (Это также помогает мне укрепить собственное понимание.)
Обратите внимание, что в случае вопроса OP вы должны использовать
duk_get_prop_string()
вместо
duk_get_prop_index()
, поскольку он на самом деле использует его больше как объект через. ключ-> доступ к значению, чем массив с использованием индексов.
Допустим, у вас есть массивы JS, вложенные в такой массив, к которому вы хотите получить доступ с помощью произвольной функции C ++:
//Javascript, calling a c++ function, passing nested arrays.
accessArray([
[ "str1", "str2" ],
//Varying the number of elements.
[ "str3", "str4", "str5" ]
]);
Затем вы регистрируете функцию в C ++ следующим образом:
//First, push the c++ function onto the Duktape stack.
//Make sure to put the # of arguments accessArray expects; in this case, it's 1.
duk_push_c_function(duktapeContext, accessArray, 1);
//Then, register that c++ function as a global JS ("string") variable,
//to access it like in the above JS.
duk_put_global_string(duktapeContext, "accessArray");
В этом контексте вы должны создать функцию C ++ следующим образом:
#include <string>
//The format of a duk_c_function.
duk_ret_t accessArray(duk_context* dc)
{
//Note: You could also first check if the parameter is an array using duk_is_array().
//Determine the number of arguments in the array parameter. In this case, the array is
//the first parameter, so it will be at the bottom of the function call stack,
//at index 0.
duk_size_t outerArraySize = duk_get_length(dc, 0);
//Loop through the outer array.
for (duk_size_t outerIndex = 0; outerIndex < outerArraySize; ++outerIndex)
{
//Get the property at [outerIndex] of the outer array (still) at
//stack index 0.
//This function puts the property at the top of the stack, at index -1.
//We'll pop it later when finished.
duk_get_prop_index(dc, 0, outerIndex);
//Now it gets a little more complicated. This time, we use the property at the top
//of the stack, at index -1, which is the inner array.
//First, we have to get its size.
//Note that this function merely returns a value; it does not change the stack.
duk_size_t innerArraySize = duk_get_length(dc, -1);
//Loop through the inner array.
for (duk_size_t innerIndex = 0; innerIndex < innerArraySize; ++innerIndex)
{
//Just like before, we get the property at [innerIndex] of the inner array
//at index -1.
//This puts the property at the top of the stack, so we'll need to pop it
//when finished.
duk_get_prop_index(dc, -1, innerIndex);
//We know/expect it as a string.
std::string myString = duk_to_string(dc, -1);
//Pop the inner array's property off the stack; now, the inner array will be
//back at the top of the stack, at index -1.
duk_pop(dc);
}
//Pop the property that we got earlier using duk_get_prop_index(); now, the
//outer array will be back at the top of the stack, at index -1.
duk_pop(dc);
}
return 0;
}
Итак, чтобы завершить круг: когда это
accessArray()
вызывается функция, стек Duktape выглядит так:
Независимо от того, получаете ли вы доступ к внешнему массиву с помощью индекса, нижнего индекса стека или верхнего индекса стека, в настоящее время нет никакой разницы.
Когда ты звонишь
duk_get_prop_index(dc, 0, outerIndex)
, он помещает элемент внешнего массива на вершину стека:
Теперь индекс
0
относится к внешнему массиву, а индекс
-1
изменился для доступа к внутреннему массиву. Затем вы можете получить доступ к элементам внутреннего массива через. например
duk_get_prop_index(dc, -1, innerIndex)
, помещая еще один элемент на вершину стека:
(bottom of stack) [ outer array, inner array, inner array element ] (top of stack)
а затем преобразовать этот элемент внутреннего массива в строку, используя
duk_to_string(dc, -1)
. Затем вы можете вставить элемент внутреннего массива, используя:
(bottom of stack) [ outer array, inner array ] (top of stack)
и снова вставьте сам внутренний массив, используя
duk_pop(dc)
:
(bottom of stack) [ outer array ] (top of stack)
Смотрите также: