JavaScript — в Ductape должен сохранить функцию обратного вызова Js передал параметр функции C

C ++ вызывает функцию JS, JsFunc (), передавая C-функцию MyCFunc () в качестве параметра. JsFunc () вызывает MyCFunc (), передавая функцию обратного вызова JS в качестве параметра.

Как сохранить в MyCFunc () параметр функции обратного вызова JS, чтобы я мог вызвать его позже из другого места в C ++?

main.cpp

#include <duktape/src/duktape.h>
#include <cassert>

duk_ret_t MyCFunc(duk_context* ctx) {
assert(duk_is_function(ctx, -1) );
(void) duk_require_function(ctx, -1);

// 1.- How to save the callback function parameter
//     so that it can be used later on, say in main()?
return 0; // nothing returned
}

int main() {
duk_context* ctx = duk_create_heap_default();
assert(ctx != nullptr);

if (duk_peval_file(ctx, "../../src/jscallback_forum/test.js") != 0) {
printf("Error: %s\n", duk_safe_to_string(ctx, -1));
exit(1);
}
duk_pop(ctx);  /* ignore result */

duk_push_global_object(ctx);
duk_bool_t isSuccess = duk_get_prop_string(ctx, -1 , "JsFunc");
assert(isSuccess != false);

// pass  MyCFunc as parameter to JsFunc
duk_push_c_function(ctx, &MyCFunc, 1); // MyCFunc expects Js callback

if (duk_pcall(ctx, 1) != 0) { // JsFunc call failed
printf("Error: %s\n", duk_safe_to_string(ctx, -1));
}

duk_pop(ctx);  /* pop duk_pcall result/error */
duk_pop(ctx);  /* pop duk_push_global_object */

// 2. How do I retrieve the JS callback function
//    saved in MyCFunc() and run it?

duk_destroy_heap(ctx);

return 0;
}

test.js

function JsFunc(cfunc) {
print("Entering testCFunc" );

cfunc(function () {
print("In lambda function()");
});

print("Exiting testCFunc");

}

2

Решение

В принципе нет никакой разницы с аналогичной функцией Ecmascript:
функция C, принимающая обратный вызов (MyCFunc в вашем примере) необходимо сохранить обратный вызов аргумента в более постоянном месте перед возвратом, чтобы его можно было найти позже.

Есть несколько вариантов для этого места хранения; эквивалентная функция Ecmascript, вероятно, сохранит ссылку на глобальный объект или некоторую структуру данных, хранящуюся в глобальном объекте (например, callbacks массив). При использовании Duktape из C вы также можете использовать один из объектов «stash», предоставленных Duktape (см. http://duktape.org/api.html#duk_push_global_stash), которые не видны в коде Ecmascript.

В качестве конкретного примера, вот как сохранить обратный вызов в глобальном объекте, предполагая, что одновременно будет сохраняться только один обратный вызов:

duk_ret_t MyCFunc(duk_context *ctx) {
/* Value stack index 0 has callback function. */

/* Equivalent to Ecmascript code: globalObject._my_callback = arg; */
duk_dup(ctx, 0);
duk_put_global_string(ctx, "_my_callback");
return 0;
}

Затем, когда вы захотите позвонить:

duk_int_t rc;

/* ... */

duk_get_global_string(ctx, "_my_callback");
rc = duk_pcall(ctx, 0);  /* no arguments in this example */
if (rc != 0) {
printf("Callback failed: %s\n", duk_safe_to_string(ctx, -1));
} else {
printf("Callback success\n");
}
duk_pop(ctx);  /* pop result */
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]