Я хотел бы знать, как выполняется шаг, описанный ниже:
Благодарю.
test.js:
function funcA() {
print("funcA()");
}
function funcB() {
print("funcB()");
}
main.cpp
int main() {
duk_context* ctx = duk_create_heap_default();
std::string byteCodeBuff; // buffer where to save the byte code;
{ // generate the bytecode from 'sourceFilePath'
const char* sourceCodeFilePath = "test.js"; // contains the JS code
// Step 1 How to 'dump' the 'sourceFilePath' to bytecode buffer ???
// get the duktape bytecode
duk_size_t bufferSize = 0;
const char* bytecode = (const char*)duk_get_buffer(ctx, -1, &bufferSize);
// save the bytecode to byteCodeBuff
byteCodeBuff.assign(bytecode,bufferSize);
duk_pop(ctx); // bytecode buffer
}
{ // load the bytecode into duktape
const size_t length = byteCodeBuff.size(); // bytecode length
const char* bytecode = &byteCodeBuff.front(); // pointer to bytecode
char* dukBuff = (char*)duk_push_fixed_buffer(ctx, length); // push a duk buffer to stack
memcpy(dukBuff, bytecode, length); // copy the bytecode to the duk buffer
// Step 2 ??? How start using the bytecode
// ??? How to invoke funcA()
// ??? How to invoke funcB()
}
duk_destroy_heap(ctx);
return 0;
}
duk_dump_function а также duk_load_function являются ли функции, предоставляемые Duktape для преобразования в и из байт-кода:
Сначала загрузите ваш файл:
// Шаг 1 (а): char * sourceCode; int sourceLen; {// загрузка из файла (простите за отсутствие ошибок ...) ifstream fscript (sourceCodeFilePath, ios :: in | ios :: binary); fscript.seekg (0, IOS :: конец); sourceLen = fscript.tellg (); буфер = новый символ [sourceLen]; fscript.seekg (0); fscript.read (SourceCode, sourceLen); }
Затем, при компиляции javascript, скрипт компилируется как «функция» (на самом деле кусок неисполненного глобального кода) в стек:
// Шаг 1 (б): // скомпилировать исходный код duk_compile_lstring (CTX, 0, SourceCode, sourceLen); // компилируется в функцию ECMAScript и помещает ее в верхнюю часть стека // сбросить код в буфер duk_dump_function (CTX); // заменяет функцию вершины стека ее байт-кодом
С этого момента остальная часть вашего кода должна забрать буфер на вершине стека.
Что касается его восстановления:
// Шаг 2 (а): // заменяет буфер на вершине стека исходной функцией duk_load_function (CTX); // так как это глобальный скрипт, он должен быть выполнен перед вызовом невидимых функций duk_call (CTX, 0); // возможно, рассмотрите возможность использования duk_pcall ()
На данный момент, ctx
глобальный объект кучи теперь содержит свойства funcA
а также funcB
,
Они могут быть получены и вызваны как таковые:
// Шаг 2 (б): // помещаем глобальный объект в стек, чтобы получить его свойства duk_push_global_object (CTX); // получаем функцию с именем «funcA» и помещаем ее в стек duk_get_prop_string (CTX, -1, "funcA"); // имя ключа / глобальное имя функции duk_require_function (CTX, -1); // Требуем, чтобы это была функция перед вызовом // теперь вызываем это! // duk_push_ * аргументы здесь duk_call (CTX, 0); // 0: количество аргументов // duk_get_ * (ctx, -1); получить возвращаемое значение // возвращаемое значение поп-функции duk_pop (CTX); // текущая вершина стека: глобальный объект // получить следующую функцию duk_get_prop_string (CTX, -1, "funcB"); // Требуем, чтобы это была функция duk_require_function (CTX, -1); // вызвать его! duk_call (CTX, 0); // всплывающее возвращение и глобальный объект вне стека duk_pop_2 (CTX);
Других решений пока нет …