https://github.com/skitsanos/node-napi-cpp
Example on how to use Node.js N-API in C++
https://github.com/skitsanos/node-napi-cpp
cpp napi node-addon node-addon-api nodejs
Last synced: 7 months ago
JSON representation
Example on how to use Node.js N-API in C++
- Host: GitHub
- URL: https://github.com/skitsanos/node-napi-cpp
- Owner: skitsanos
- License: mit
- Created: 2021-08-23T11:57:16.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2024-03-05T07:54:36.000Z (over 1 year ago)
- Last Synced: 2025-01-15T20:19:54.989Z (9 months ago)
- Topics: cpp, napi, node-addon, node-addon-api, nodejs
- Language: C++
- Homepage:
- Size: 23.4 KB
- Stars: 2
- Watchers: 3
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# node-napi-cpp
Example on how to use Node.js N-API in C++### Dependencies
- *node-cmake* - A CMake-based build system for Node.js native modules
- *node-addon-api* - This module contains header-only C++ wrapper classes which simplify the use of the C based Node-API provided by Node.js when using C++. It provides a C++ object model and exception handling semantics with low overhead
- *cmake-js* - CMake.js is a Node.js/io.js native addon build tool which works (almost) exactly like node-gyp, but instead of gyp, it is based on CMake build system.Install dependencies before doing anything:
```sh
yarn add node-cmake node-addon-api cmake-js
```### CMakeLists.txt
Tested on Node.js 12, 14 and 16, configuration made in a way that it usses `node-cmake` and `node-addon-api` bits installed earlier, so all your headers are in place and no additional configuration required. Well, just change your project name instead `demo` into something you like more at line #14.
### Calling JS module from C++
`DemoClass.cpp` demonstrates how to call `require` from C++. There is one thing about it that not really documented on Node.js references and manuals -- `require` is not a part of Node.js internals and available only at run time, so you can't call it directly in any way within your C++ add-on, but you can pass it to your add-on.
```js
const addon = require('../build/Release/demo');
const demo = new addon.DemoClass(require);
```So let's say you have a JavaScript module `hi.js` that will be called in DemoClass:
```js
const welcome = () => 'Welcome back!';module.exports = welcome;
```In DemoClass constructor we pass `require` and we keep it for the future use:
```cpp
DemoClass::DemoClass(const CallbackInfo &args) : ObjectWrap(args) {
this->_env = args.Env();if (args.Length() < 1 || !args[0].IsFunction()) {
Napi::TypeError::New(this->_env, "Function expected").ThrowAsJavaScriptException();
}//
// verify arguments passed to ensure that it was the {require} function that was sent as an ergument
//
Napi::Function require = args[0].As();std::regex self_regex("^function require\\(path\\)",
std::regex_constants::ECMAScript | std::regex_constants::icase);if (!std::regex_search(require.ToString().Utf8Value().c_str(), self_regex)) {
Napi::TypeError::New(this->_env, "{require} Function expected").ThrowAsJavaScriptException();
}this->_require = Persistent(require);
}
```Since we know the `require` function signature we can check if it is the right one with a basic regular expression... Now we can build a method that will consume that `require`. So, literally, we tell C++ to perform `require('./hi')` that will return a fucntion and then call that function.
```cpp
Napi::String DemoClass::sayHi(const CallbackInfo &args) {
Napi::Env env = args.Env();std::vector jsArgs = {String::New(env, "./hi")};
Napi::Function f = this->_require.Call(jsArgs).As();
auto result = f.Call({}).As().Utf8Value();return Napi::String::New(this->_env, result);
}
```So now, when we call this methods from Javascript:
```js
console.log(demo.sayHi());
```It will print out our 'Welcome back!' message