javascript - 如何在 Duktape 中创建 C++ 对象
问题描述
基于http://wiki.duktape.org/HowtoNativeConstructor.html,我可以创建一个 c++ 类并导出到 JavaScript,JavaScript 代码也可以创建对象
但。当我在 C++ 本机代码中创建一个对象时,它无法工作,JavaScript 代码看不到该对象
我从 Duktape 收到错误消息:“TypeError:无法读取属性”
我的代码是:
class Btn
{
public:
void test()
{
printf("%s\r\n", __PRETTY_FUNCTION__);
}
};
Btn btn;
/* btn.prototype.test */
duk_ret_t btn_test(duk_context *ctx)
{
printf("%s\r\n", __PRETTY_FUNCTION__);
duk_push_this(ctx);
duk_get_prop_string(ctx, -1, "\xff""\xff""Btn");
Btn *x = static_cast<Btn *>(duk_to_pointer(ctx, -1));
if (x)
{
x->test();
}
printf("Btn Addr 0x%08x\r\n", x);
duk_pop(ctx);
return 0;
}
duk_ret_t btn_destructor(duk_context *ctx)
{
printf("%s\r\n", __PRETTY_FUNCTION__);
return 0;
}
/* btn */
duk_ret_t btn_constructor(duk_context *ctx)
{
printf("%s\r\n", __PRETTY_FUNCTION__);
if (!duk_is_constructor_call(ctx))
{
return DUK_RET_TYPE_ERROR;
}
duk_push_this(ctx);
printf("Btn Addr 0x%08x\r\n", &btn);
duk_push_pointer(ctx, &btn);
duk_put_prop_string(ctx, -2, "\xff""\xff""Btn");
duk_push_c_function(ctx, btn_destructor, 1);
duk_set_finalizer(ctx, -2);
return 0;
}
void btn_init(duk_context *ctx)
{
duk_push_c_function(ctx, btn_constructor, 0);
duk_push_object(ctx);
duk_push_c_function(ctx, btn_test, 0);
duk_put_prop_string(ctx, -2, "test");
duk_put_prop_string(ctx, -2, "prototype");
duk_put_global_string(ctx, "Btn");
}
duk_ret_t getBtn(duk_context *ctx)
{
printf("%s\r\n", __PRETTY_FUNCTION__);
int n = duk_get_top(ctx);
if (n != 1)
{
return DUK_EXEC_ERROR;
}
// get "MyButton"
std::string str(duk_to_string(ctx, 0));
// create Btn object
duk_get_global_string(ctx, "Btn");
duk_new(ctx, 0);
duk_push_object(ctx);
return DUK_EXEC_SUCCESS;
}
static duk_ret_t duk__print(duk_context *ctx) {
duk_push_string(ctx, " ");
duk_insert(ctx, 0);
duk_join(ctx, duk_get_top(ctx) - 1);
printf("%s\n", duk_safe_to_string(ctx, -1));
return 0;
}
int main(int argc, char *argv[]) {
duk_context *ctx = duk_create_heap_default();
duk_push_c_function(ctx, duk__print, DUK_VARARGS);
duk_put_global_string(ctx, "print");
btn_init(ctx);
duk_push_global_object(ctx);
duk_push_c_function(ctx, getBtn, 1);
duk_put_prop_string(ctx, -2, "getBtn");
duk_pop(ctx);
printf("------- Script 1 -------\r\n");
{
std::string script1 = "btn = getBtn(\"MyButton\");" \
"print(btn);" \
"btn.test()";
duk_push_string(ctx, script1.c_str());
if (duk_peval(ctx) != 0)
{
printf("eval failed: %s\n", duk_safe_to_string(ctx, -1));
}
duk_pop(ctx);
}
printf("------- Script 2 -------\r\n");
{
std::string script2 = "btn = new Btn();" \
"print(btn);" \
"btn.test();";
duk_push_string(ctx, script2.c_str());
if (duk_peval(ctx) != 0)
{
printf("eval failed: %s\n", duk_safe_to_string(ctx, -1));
}
duk_pop(ctx);
}
duk_destroy_heap(ctx);
return 0;
}
输出结果:
-------- 脚本 1 -------- duk_ret_t getBtn(duk_context*) duk_ret_t btn_constructor(duk_context*) Btn 地址 0x00476030 duk_ret_t btn_destructor(duk_context*) 不明确的 评估失败:TypeError:无法读取未定义的属性“测试” ------- 脚本 2 ------- duk_ret_t btn_constructor(duk_context*) Btn 地址 0x00476030 [对象对象] duk_ret_t btn_test(duk_context*) 无效 Btn::test() Btn 地址 0x00476030 duk_ret_t btn_destructor(duk_context*)
如何在getBtn(C++ 本机代码)函数中创建 JavaScript 对象,并将对象返回给 JavaScript 代码?
解决方案
使用duk_new从 C++ 代码生成 JS 类的实例。此调用需要一个构造函数和 duk 堆栈上的参数。
/* Assume target function is already on stack at func_idx.
* Equivalent to Ecmascript 'new func("foo", 123)'.
*/
duk_idx_t func_idx = /* ... */;
duk_dup(ctx, func_idx);
duk_push_string(ctx, "foo");
duk_push_int(ctx, 123);
duk_new(ctx, 2); /* [ ... func "foo" 123 ] -> [ ... res ] */
printf("result is object: %d\n", (int) duk_is_object(ctx, -1));
duk_pop(ctx);
推荐阅读
- javascript - 关于 NodeJS 缓冲区
- excel - Excel:通过多个工作表进行相关的下拉计算(具有不同的列位置)
- jquery - 在 JSON 对象数组中查找具有某些值的项目并替换(如果存在)
- java - JMeter - 每个线程中的第一个样本很慢,问题每隔约 210 秒重复一次
- marklogic - 如何使用 MarkLogic 中的结构化查询从值列表中获取最大值(日期)
- docker-compose - 在 Win 10 上使用 Docker-Compose 构建 vlc-unity 时出错
- android - Android webview cookie不像chrome那样工作
- regex - 带有通配符搜索的正则表达式?
- jenkins - 如何在 Jenkins 管道中按 buildnumber 停止构建
- python - matplotlib 中的动画箭头