Thursday, September 12, 2019

C++ Node files Looking into details and adding a method

Below is some description of main.cpp file

1. #include includes the napi header file so that we can access all the helper macros, classes and functions.
2. NODE_API_MODULE is a macro that accepts modulename and registerfunction as parameters.
3. In our case registerfunction is InitAll and it takes two parameters which are passed by N-API. First parameter env is the context that needs to be passed on to most N-API function and exports is the object used to set the exported functions and classes via N-API.


/**
* This code defines the entry-point for the Node addon, it tells Node where to go
* once the library has been loaded into active memory. The first argument must
* match the "target" in our *binding.gyp*. Using NODE_GYP_MODULE_NAME ensures
* that the argument will be correct, as long as the module is built with
* node-gyp (which is the usual way of building modules). The second argument
* points to the function to invoke. The function must not be namespaced.
*/
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)


Now to add a method to the C++ function using N-API

std::string hello(){
  return "Hello World";
}

To export this to javascript side, we have to do quite lot of work!

We need to have a header file and a cpp file containing implementations

Below given is hellosample.h

#include
namespace hellosample {
  std::string hello();
  Napi::String HelloWrapped(const Napi::CallbackInfo& info);
  Napi::Object Init(Napi::Env env, Napi::Object exports);
}


#include "hellosample.h"
std::string hellosample::hello(){
  return "Hello World";
}
Napi::String hellosample::HelloWrapped(const Napi::CallbackInfo& info)
{
  Napi::Env env = info.Env();
  Napi::String returnValue = Napi::String::New(env, hellosample::hello());

  return returnValue;
}
Napi::Object hellosample::Init(Napi::Env env, Napi::Object exports)
{
  exports.Set(
"hello", Napi::Function::New(env, hellosample::HelloWrapped)
  );

  return exports;
}


For every function in C++ we want to export we will basically create a NAPI wrapped function (HelloWrapped in this example) and add it to the exports object using Init.
Every wrapped function that needs to be exported to JS should have input params/return value from the Napi namespace.

Every wrapped function takes in CallbackInfo as the input parameter. This contains things like the context and the input parameters that needs to be passed to the function.
Initfunction is used to just set the export key as hello with corresponding wrapped function HelloWrapped .


OK, having defined these extra files, we need to tell the node gyp that we have added these files.This includes making changes to the binding.gyp, main.cpp, index.js files
Below is how to do that


In the gyp file, in the sources array, add the new file that is to be compiled. The new gyp file will be like this below

"sources": [
-            "cppsrc/main.cpp"
+            "cppsrc/main.cpp",
+            "cppsrc/Samples/functionexample.cpp"
         ],


main.cpp will be like this below

 #include
+#include "Samples/functionexample.h"

 Napi::Object InitAll(Napi::Env env, Napi::Object exports) {
-  return exports;
+  return functionexample::Init(env, exports);
 }

index.js can be like below

 const testAddon = require('./build/Release/testaddon.node');
 console.log('addon',testAddon);
+console.log(testAddon.hello());
 module.exports = testAddon;


References:
https://medium.com/@atulanand94/beginners-guide-to-writing-nodejs-addons-using-c-and-n-api-node-addon-api-9b3b718a9a7f

No comments:

Post a Comment