NodeJS C++ Addon - Examples
Here you will find examples using C++ functions via NodeJS addon (NAPI), one uses the Win32 API to display a dialog window, another to sum two numbers together and the final method executes a javascript call back function with parameters.
Projects 2020
NodeJS Addon Examples
Introduction
I have listed examples for building an NAPI addons this addon uses the Win32 API to display a GUI dialog Message. Another example which adds two floating point numbers together, and a method that calls a javascript call back function with a parameter defined pass for the script to process.

I have created to new source files to hold these methods, named myAddon.h and myAddon.cpp. These files are listed under the cppsrc folder created when preparing the addon. They are also added to the binding.gpy file under sources array. And the main.cpp has changed to call the myAddon Init function is inside the NAPI InitAll function.
NodeJS Addon Examples - Source Code
main.cpp
#include <napi.h>
#include "myAddon.h"
Napi::Object InitAll(Napi::Env env, Napi::Object exports){
return myAddon::Init(env, exports);
}
NODE_API_MODULE(exampleAddon, InitAll)
myAddon.h
#include <napi.h>
#include <string>
namespace myAddon{
// Initialize Link Function
Napi::Object Init(Napi::Env env, Napi::Object exports);
// C++ Function to show a Windows API Dialog Box Message
void ShowMessage(std::string msg);
// C++ Method of adding two numbers
float Sum(float a, float b);
// Show Message Wrapper Function
Napi::String ShowMessageWrapper(const Napi::CallbackInfo& info);
// function to sum two numbers, passed from javascript
Napi::Number SumWrapper(const Napi::CallbackInfo& info);
// Callback Function
Napi::String executeCallbackWrapper(const Napi::CallbackInfo& info);
}
myAddon.cpp
#include "myAddon.h"
#include <windows.h>
#include <sstream>
// C++ Function
void myAddon::ShowMessage(std::string msg){
// Win32 API Specific function...
MessageBoxA(NULL, msg.c_str(), "Demo Windows Function", MB_OK);
}
// C++ Method of adding two numbers
float myAddon::Sum(float a, float b){
return a + b;
}
// Show Message - Wrapper Function
Napi::String myAddon::ShowMessageWrapper(const Napi::CallbackInfo& info)
{
Napi::Env env = info.Env();
// Parameter Type Checking
if(!info[0].IsString()){
Napi::TypeError::New(env, "String Expected").ThrowAsJavaScriptException();
}
// Get First Parameter as string
Napi::String msg = info[0].As<Napi::String>();
// Execute C++ function
ShowMessage(msg);
// Return Empty String
return Napi::String::New(env, "");
}
// Sum C++ - wrapper function
Napi::Number myAddon::SumWrapper(const Napi::CallbackInfo& info){
// Get Environment
Napi::Env env = info.Env();
// Parameter Type Checking
if(info.Length() != 2 || !info[0].IsNumber() || !info[1].IsNumber()){
Napi::TypeError::New(env, "Numbers Expected").ThrowAsJavaScriptException();
}
// Get Parameters a,b as numbers
Napi::Number a = info[0].As<Napi::Number>();
Napi::Number b = info[1].As<Napi::Number>();
// Execute Sum C++ function
float result = myAddon::Sum(a,b);
// Return results of sum
return Napi::Number::New(env, result);
}
Napi::Object myAddon::Init(Napi::Env env, Napi::Object exports)
{
// Export new function called "showMessage", this is callable from javascript
exports.Set("showMessage", Napi::Function::New(env, myAddon::ShowMessageWrapper));
// Export new function called "sum", this is callable from javascript
exports.Set("sum", Napi::Function::New(env, myAddon::SumWrapper));
// Export new function called "stringProcess", this is callable from javascript
// and has a callback function as parameter
exports.Set("stringProcess", Napi::Function::New(env, myAddon::executeCallbackWrapper));
return exports;
}
// Callback Function Example
Napi::String myAddon::executeCallbackWrapper(const Napi::CallbackInfo& info)
{
// Get Environment
Napi::Env env = info.Env();
std::stringstream ss;
// Parameter Type Checking
if(info.Length() != 2 || !info[0].IsString() || !info[1].IsFunction()){
Napi::TypeError::New(env, "String Expected, and expected callback function").ThrowAsJavaScriptException();
}
std::string str = info[0].ToString().Utf8Value();
ss << "Processed : " << str;
// Cast First parameter as function, this is the callback function in javascript
Napi::Function cb = info[1].As<Napi::Function>();
// Execute callback function now, passing the new string as a parameter
cb.Call(env.Global(), {Napi::String::New(env, ss.str())});
return Napi::String::New(info.Env(), "Success");
}
binding.gyp
This file is in the Nodejs project directory where the package.json file is located.
{
"targets": [{
"target_name": "myAddon",
"cflags!": [ "-fno-exceptions" ],
"cflags_cc!": [ "-fno-exceptions" ],
"sources": [
"cppsrc/main.cpp",
"cppsrc/myAddon.h",
"cppsrc/myAddon.cpp"
],
'include_dirs': [
"<!@(node -p \"require('node-addon-api').include\")"
],
'libraries': [],
'dependencies': [
"<!(node -p \"require('node-addon-api').gyp\")"
],
'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ]
}]
}
index.js
This file is in the Nodejs project directory where the package.json file is located.
const myAddon = require('./build/Release/myAddon.node');
module.exports = myAddon;
// Call showMessage C++ function
myAddon.showMessage("Display this message");
// Call sum C++ function, display the results
console.log(myAddon.sum(0.5, 0.75));
// Example of parameter function callback
console.log(myAddon.stringProcess("Callback", function(data){
console.log(data);
}));