在Ductape中必须保存一个Js Callback函数,将一个参数传递给C函数

时间:2016-03-09 11:55:29

标签: javascript c++ duktape

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");

}

1 个答案:

答案 0 :(得分:2)

原则上与类似的Ecmascript功能没有区别: 接受回调的C函数(在您的示例中为MyCFunc)需要在返回之前将参数回调存储到更持久的位置,以便以后可以查找它。

该存储位置有多种选择;等效的Ecmascript函数可能会存储对全局对象的引用或全局对象中保存的某些数据结构(例如callbacks数组)。当使用C语言中的Duktape时,你也可以使用其中一个&#34; stash&#34; 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 */