把 JavaScript 函数传入到一个 C++ 函数并在那里执行它们,这在插件里是常见的做法。 以下例子描述了如何调用这些回调:

    1. // addon.cc
    2. #include <node.h>
    3. namespace demo {
    4. using v8::Context;
    5. using v8::Function;
    6. using v8::FunctionCallbackInfo;
    7. using v8::Isolate;
    8. using v8::Local;
    9. using v8::Null;
    10. using v8::Object;
    11. using v8::String;
    12. using v8::Value;
    13. void RunCallback(const FunctionCallbackInfo<Value>& args) {
    14. Isolate* isolate = args.GetIsolate();
    15. Local<Context> context = isolate->GetCurrentContext();
    16. Local<Function> cb = Local<Function>::Cast(args[0]);
    17. const unsigned argc = 1;
    18. Local<Value> argv[argc] = {
    19. String::NewFromUtf8(isolate,
    20. "hello world").ToLocalChecked() };
    21. cb->Call(context, Null(isolate), argc, argv).ToLocalChecked();
    22. }
    23. void Init(Local<Object> exports, Local<Object> module) {
    24. NODE_SET_METHOD(module, "exports", RunCallback);
    25. }
    26. NODE_MODULE(NODE_GYP_MODULE_NAME, Init)
    27. } // namespace demo

    注意,该例子使用了一个带有两个参数的 Init(),它接收完整的 module 对象作为第二个参数。 这使得插件可以用一个单一的函数完全地重写 exports,而不是添加函数作为 exports 的属性。

    为了验证它,运行以下 JavaScript:

    1. // test.js
    2. const addon = require('./build/Release/addon');
    3. addon((msg) => {
    4. console.log(msg);
    5. // 打印: 'hello world'
    6. });

    在这个例子中,回调函数是被同步地调用。