0

我为 OpenCPN 海上导航程序创建了一个插件,它结合了 Duktape 以提供脚本功能。OpenCPN 使用 wxWidgets。

基本上,该插件为用户提供了一个控制台,该控制台包括一个脚本窗口、一个输出窗口和各种按钮。用户输入他们的脚本(或从 .js 文件加载它)并单击运行。该脚本使用 duk_peval 运行。返回时,我会显示结果,销毁上下文并等待用户再次运行,可能是在修改脚本之后。这一切运作良好。但是,请考虑以下测试脚本:

add(2, 3);

function add(a, b){
    if (a == b) throw("args match");
    return(a + b);
    }

如果 add 调用中的两个参数相等。该脚本会引发错误,用户可以重试。这一切都有效。

现在我可以将 add实现为 c++ 函数:

static duk_ret_t add(duk_context *ctx){
    int a, b;
    a = duk_get_int(ctx, 0);
    b = duk_get_int(ctx, 1);
    if (a == b){
            duk_error(ctx, DUK_ERR_TYPE_ERROR, "args match");
                 }
    duk_pop_2(ctx);
    duk_push_int(ctx, a+b);
    return (1);
    }

如所写,这会将错误传递给致命错误处理程序。我知道我不能尝试进一步使用 Duktape,但我可以显示错误 OK。但是,我没有办法回到插件。规定的操作是退出或中止,但这些都终止托管应用程序,这是绝对不可接受的。理想情况下,我需要能够从 duk_peval 调用中返回错误。

我尝试使用来自外部 C++ 函数的 duk_pcall 运行 add 函数。这会捕获错误,我可以从该外部函数中显示它。但是当我从那个外部函数返回时,脚本在不应该的时候继续执行,并且从 duk_peval 调用的最终返回不知道错误。

我知道我可以在脚本中使用 try/catch,但可能会调用数十次 OpenCPN API,这是不现实的。将错误返回代码一直渗透回去,可能通过几个 C++ 函数,然后到顶层脚本也将非常麻烦,因为脚本和函数可能非常复杂。

谁能建议一种将控制权传回给我的调用插件的方法-最好是从 duk_peval 返回?

4

1 回答 1

0

我终于破解了这个。

首先,我在错误情况下使用以下内容:

if (a == b){
    duk_push_error_object(ctx, DUK_ERR_ERROR, "args match");
    duk_thow(ctx);
    }

如果抛出错误,则 duk_peval 和 duk_pcall 的返回值不为零,并且错误对象在堆栈上 - 如文档所述

现在对我来说一切都很好。

于 2020-11-07T09:32:25.363 回答