#duktape
Вопрос:
Мы находимся в процессе внедрения JS в наше приложение, и мы будем использовать несколько десятков сценариев, каждый из которых назначен для события. Внутри этих сценариев мы предоставляем минимальный api обратного вызова,
function onevent(value)
{ // user javascript code here
}
который вызывается всякий раз, когда происходит это событие. Сценарии должны иметь свой собственный глобальный, так как эта функция всегда имеет одно и то же имя, и мы получаем доступ к ней из кода cpp с помощью
duk_get_global_string(js_context_duk, "onevent");
duk_push_number(js_context_duk, val);
if (duk_pcall(js_context_duk, 1) != 0)
{
printf("Duk error: %sn", duk_safe_to_string(js_context_duk, -1));
}
duk_pop(js_context_duk); /* ignore result */
Опять же, мы хотим обеспечить минимальную связь между сценариями, например
Сценарий 1
var a = 1;
function onevent(val)
{
log(a);
}
Сценарий 2
function onevent(val)
{
a ;
}
Есть ли способ достичь этого? Может быть, путем введения собственного глобального объекта «ueber», который определяется один раз и на который можно ссылаться везде? Должно быть возможно добавить свойства к этому «глобальному объекту ueber» из любого скрипта, например
Сценарий 1
function onevent(val)
{
log(ueber.a);
}
Сценарий 2
function onevent(val)
{
ueber.a=1;
}
Ответ №1:
Вместо простых файлов JS вы могли бы использовать модули. duktape поставляется с примером кода для реализации модульной системы (включая ее изоляцию кода), как в Node.js. Имея это на месте, вы можете экспортировать переменные, которые должны быть доступны для совместного использования.
Комментарии:
1. Спасибо вам за ваш ответ! Но я проверил модульный подход, и кэш модуля связан с глобальным объектом контекста через duk_push_global_stash(ctx) в duk_module_node.c, поэтому модули не имеют желаемого «одноэлементного» поведения, или я что-то пропустил? Вот что говорится в примере связанного кода: «После этих шагов require() будет зарегистрирован в глобальном объекте, и система модулей готова к использованию».
Ответ №2:
У нас есть подход, который, похоже, работает и сейчас. После создания нового контекста с
duk_push_thread_new_globalenv(master_ctx);
new_ctx = duk_require_context(master_ctx, -1);
duk_copy_element_reference(master_ctx, new_ctx, "ueber");
мы выполняем эту последовательность вызовов для всех свойств/объектов/функций, созданных в основном контексте:
void duk_copy_element_reference(duk_context* src, duk_context* dst, const char* element)
{
duk_get_global_string(src, element);
duk_require_stack(dst, 1);
duk_xcopy_top(dst, src, 1);
duk_put_global_string(dst, element);
}
Кажется, это работает (потому что все находится в одной куче и все однопоточные). Может быть, кто-нибудь с более глубоким пониманием duktape может прокомментировать это? Является ли это осуществимым решением без побочных эффектов?
правка: отметьте это как ответ. работает, как и ожидалось, никаких утечек памяти или других проблем.