捕获从 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 并且错误对象在堆栈上 - 如文档所述
现在对我来说一切都很好。
我已经为 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 并且错误对象在堆栈上 - 如文档所述
现在对我来说一切都很好。