捕获从 Duktape 调用的 C++ 函数中的错误并从中恢复

Catching and recovering from error in C++ function called from Duktape

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

基本上,该插件向用户展示了一个包含脚本 window、输出 window 和各种按钮的控制台。用户输入他们的脚本(或从 .js 文件加载它)并单击 运行。该脚本是 运行 使用 duk_peval。在 return 上,我显示结果,销毁上下文并等待用户再次 运行,也许是在修改脚本之后。这一切都很好。但是,请考虑以下测试脚本:

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 调用中 return。

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

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

任何人都可以建议一种将控制权传回我的调用插件的方法 - 最好是通过 returning 来自 duk_peval?

终于破解了

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

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

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

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