【问题标题】:How to statically store and call a node.js callback function如何静态存储和调用 node.js 回调函数
【发布时间】:2016-07-19 03:50:18
【问题描述】:

我有一个为节点 0.10 开发的 node.js 插件,我需要为当前节点更新它。我修复了大部分 api 更改,但我遇到了静态存储回调指针以供以后调用的问题。我修改了 3_callback 示例插件以显示到目前为止我所做的以及我在编译期间遇到的错误。这是我目前所拥有的(编译错误添加为注释行):

#include <node.h>

using namespace v8;

typedef Persistent<Function> CallBack_t;

static CallBack_t MyCallBack;

void CallBack( char* str ) {
  Isolate* isolate = Isolate::GetCurrent();
  HandleScope scope( isolate );

  const unsigned argc = 1;
  Local<Value> argv[ argc ] = { String::NewFromUtf8( isolate, str ) };
  Local<Function> cb = Local<Function>::New( isolate, MyCallBack );
  cb->Call( isolate->GetCurrentContext()->Global(), argc, argv );
}

void RunCallback( const FunctionCallbackInfo<Value>& args ) {
  Isolate* isolate = Isolate::GetCurrent();
  HandleScope scope( isolate );

  Local<Function> cb = Local<Function>::Cast( args[ 0 ] );
  MyCallBack = CallBack_t::New( isolate, cb );
  //..\addon.cc( 24 ) : error C2664 : 'v8::Function *v8::PersistentBase<T>::New(v8::Isolate *,T *)' : cannot convert argument 2 from 'v8::Local<v8::Function>' to 'v8::Function *' [E:\SoftwareProjects\node-addon-examples\trunk\3_global_callback\node_0.12\build\addon.vcxproj]
  //   with
  //   [
  //      T = v8::Function
  //   ]
  //..\addon.cc( 24 ) : note : No user - defined - conversion operator available that can perform this conversion, or the operator cannot be called  CallBack( "JavaScriptCallBack calling" );
}

void Init( Handle<Object> exports, Handle<Object> module ) {
  NODE_SET_METHOD( module, "exports", RunCallback );
}

NODE_MODULE( addon, Init )

我尝试了不同的替代方案,但到目前为止都没有。哪里出错了?

【问题讨论】:

  • 提示:您应该使用nan 以获得更好的跨 v8 版本的兼容性。 nan 还在幕后处理了许多其他事情,尤其是在调用回调时(例如确保在引发异常的情况下在适当的活动域中调用它)。
  • 感谢 mscdex 的建议。我可以修改插件,以便它使用 nan 构建和执行。

标签: node.js windows callback add-on


【解决方案1】:

解决代码中的错误:

cannot convert argument 2 from 'v8::Local&lt;v8::Function&gt;' to 'v8::Function *'

这应该可以解决它:

v8::Local<v8::Function> cb = std::Local<v8::Function>::Cast(args[0]);
v8::Function * f_ptr = *cb;

用于在 Node V8 版本 4.X.X 中静态存储和调用 JS-Callback 函数:
callbacks.cxx:

v8::Persistent<v8::Function> r_call;

/** Save the JS-Callback for later use.
 *  If args[0] is not a function (such as null), remove callback
 */
void RunCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
    v8::Isolate* isolate = args.GetIsolate();
    if (args[0]->IsFunction()) {
        v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(args[0]);
        v8::Function * ptr = *func;
        r_call.Reset(isolate, func);
    }
    else {
        r_call.Reset();
    }
}

/* Run the saved callback if there is one. */
void run() {
    if(!r_call.IsEmpty()) {
        v8::Isolate* isolate = v8::Isolate::GetCurrent();
        v8::Local<v8::Function> func = v8::Local<v8::Function>::New(isolate, r_call);

        if (!func.IsEmpty()) {
            const unsigned argc = 1;
            v8::Local<v8::Value> argv[argc] =
                { v8::String::NewFromUtf8(isolate, "hello world") };
            func->Call(v8::Null(isolate), argc, argv);
        }
    }
}

test.js:

const mod = require("...");
mod.RunCallback((msg) => { console.log(msg); });
mod.run();

-- 测试:node-gyp v4.4.4、MSVS2013、SWIGv3.0.10 --

【讨论】:

  • 真是巧合。几个月后我才回到这个项目。我会尝试你的代码,因为我想避免 NAN 依赖。谢谢。
  • 所以效果很好。我将您的答案标记为有用...哎呀,我不能。我的声望不够。
  • (但是,您不需要声誉来将其标记为正确。如果这是您正在寻找的答案,您应该将其标记为正确,以便其他人也可以找到它。)
  • 将其标记为正确。晚了,我知道但已经完成了。非常感谢。
  • 这个技巧还可以保存和重用 C++ 中定义的 js 类(带有原型方法、访问器等的函数模板。当我无法获取 node::ObjectWrap (或 Nan:: ObjectWrap) 屈服于我的意愿,在此过程中消除大量样板集成代码。
猜你喜欢
  • 2014-04-14
  • 1970-01-01
  • 1970-01-01
  • 2013-10-16
  • 1970-01-01
  • 2011-10-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多