Luke
Luke

Reputation: 614

C++ add-on for NodeJS nested functions not being called

I am writing a c++ NodeJs native add-on using the v8 that implements a minimax tic-tac-toe AI.

I have a problem where nested functions are not working.

Here is my code:

namespace Game {
    Move bestMove(...) {
        // implementation
    }
}
namespace addon {
    using namespace v8;
    using std::vector;
    ...

    // this function returns the best move back to nodejs
    void bestMove(const FunctionCallbackInfo<Value>& args) {
        Isolate* isolate = args.GetIsolate();
        ...

        auto returnVal = Game::bestMove(params); // Game::bestMove() returns the best move for the computer

        args.GetReturnValue().Set((returnVal.row * 3) + returnVal.col); // returns the move back to nodejs
}

Normally, if the game board is this (computer is o):

    x _ _
    _ _ _
    _ _ _

The function shouldn't return 0 because it is already taken by x. However it seems to always return 0.

After I investigated a bit, I realized that the function Game::bestMove() never gets called.

Add yes, I know this is the problem because after I added std::cout << "Computing"; in the function Move bestMove(), it never got printed to the console.

However, if I add std::cout << "Computing"; in the function addon::bestMove(), it works.

There is also no compile time error thrown.

Thanks for any help.

Upvotes: 2

Views: 397

Answers (1)

bmacnaughton
bmacnaughton

Reputation: 5308

This answer is only helpful if you're willing to move to using N-API via the C++ bindings, node-addon-api (available via npm). You're using C++ so it is probably the cleanest way to make the coding more straightforward and likely to work. Net, I can't tell you what is wrong with your code from what's posted, so if that's showstopper then no need to read on.

With node-addon-api your addon would look something like:

#include <napi.h>

// your move function
Napi::Value bestMove(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();

  int move = Game::bestMove(params);

  // just return the number and the C++ inline wrappers handle
  // the details
  return Napi::Number::New(env, move);
}

// the module init function used in the NODE_API_MODULES macro below
Napi::Object Init(Napi::Env env, Napi::Object exports) {
  Napi::HandleScope scope(env);

  // expose the bestMove function on the exports object.
  exports.Set("bestMove", Napi::Function::New(env, bestMove));

  return exports;
}

NODE_API_MODULES(my_game, Init)

In JavaScript you'd just require the bindings file, typically in build/Release/my_game.node (or use the bindings package so you can just require('my_game')). So

const game = require('my_game')
...

move = game.bestMove()

I don't know enough details to flesh out the example any better.

I worked with Nan before the node-addon-api package and found it frustrating. I didn't try using V8 directly because it ties my application to a specific version of node.

If you're interested in more details check out https://github.com/nodejs/node-addon-api. It really quite well done.

Apologies if any of the code above has errors; I just made it up as I went.

Upvotes: 2

Related Questions