diff --git a/1_hello_world/napi/binding.gyp b/1_hello_world/napi/example1/binding.gyp similarity index 100% rename from 1_hello_world/napi/binding.gyp rename to 1_hello_world/napi/example1/binding.gyp diff --git a/1_hello_world/napi/hello.cc b/1_hello_world/napi/example1/hello.cc similarity index 100% rename from 1_hello_world/napi/hello.cc rename to 1_hello_world/napi/example1/hello.cc diff --git a/1_hello_world/napi/hello.js b/1_hello_world/napi/example1/hello.js similarity index 100% rename from 1_hello_world/napi/hello.js rename to 1_hello_world/napi/example1/hello.js diff --git a/1_hello_world/napi/package.json b/1_hello_world/napi/example1/package.json similarity index 100% rename from 1_hello_world/napi/package.json rename to 1_hello_world/napi/example1/package.json diff --git a/1_hello_world/napi/example2/libHelloWorld/.gitignore b/1_hello_world/napi/example2/libHelloWorld/.gitignore new file mode 100644 index 00000000..567609b1 --- /dev/null +++ b/1_hello_world/napi/example2/libHelloWorld/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/1_hello_world/napi/example2/libHelloWorld/README.md b/1_hello_world/napi/example2/libHelloWorld/README.md new file mode 100644 index 00000000..cff23ffb --- /dev/null +++ b/1_hello_world/napi/example2/libHelloWorld/README.md @@ -0,0 +1,25 @@ +This example covers handling of UTF-8 encoded strings as parameters for an external C library. It goes beyond the demonstration of the initial example, seen in the `example1` folder. Combining both examples together should result in a clearer and more complete view of how to use the NAPI for this type of use cases. + +1. Dependencies +``` +gcc +python2 +nodejs +node-gyp +``` +Installable on Debian-based systems like this: +``` +sudo apt install build-essential python2 nodejs node-gyp +``` + +2. Building and running the project: +``` +cd node-addon-examples/1_hello_world/napi/example2/libHelloWorld/ +./build.sh +``` +This will execute `build.sh` which will compile `libHelloWorld.so` within `lib/`. Afterwards, the shared object will be copied to `/usr/lib` and its header will be copied to `/usr/include`. Done that, the NAPI module will be built and `module.js` will be executed. + +3. Once the previous steps were finished successfully, the output should be as follows: +``` +Hello concat World equals HelloWorld +``` diff --git a/1_hello_world/napi/example2/libHelloWorld/binding.gyp b/1_hello_world/napi/example2/libHelloWorld/binding.gyp new file mode 100644 index 00000000..9ed16fd5 --- /dev/null +++ b/1_hello_world/napi/example2/libHelloWorld/binding.gyp @@ -0,0 +1,9 @@ +{ + "targets": [ + { + "target_name": "module", + "sources": [ "./src/module.c" ], + "libraries": [ "/usr/lib/libHelloWorld.so" ] + } + ] +} diff --git a/1_hello_world/napi/example2/libHelloWorld/build.sh b/1_hello_world/napi/example2/libHelloWorld/build.sh new file mode 100755 index 00000000..38688dfb --- /dev/null +++ b/1_hello_world/napi/example2/libHelloWorld/build.sh @@ -0,0 +1,4 @@ +sudo ./lib/build.sh && \ +node-gyp configure build && \ +sudo node module.js +exit 0 diff --git a/1_hello_world/napi/example2/libHelloWorld/lib/build.sh b/1_hello_world/napi/example2/libHelloWorld/lib/build.sh new file mode 100755 index 00000000..57da271b --- /dev/null +++ b/1_hello_world/napi/example2/libHelloWorld/lib/build.sh @@ -0,0 +1 @@ +./compileLibHelloWorld.sh && sudo cp libHelloWorld.so /usr/lib && sudo cp libHelloWorld.h /usr/include diff --git a/1_hello_world/napi/example2/libHelloWorld/lib/compileLibHelloWorld.sh b/1_hello_world/napi/example2/libHelloWorld/lib/compileLibHelloWorld.sh new file mode 100755 index 00000000..3d7a2680 --- /dev/null +++ b/1_hello_world/napi/example2/libHelloWorld/lib/compileLibHelloWorld.sh @@ -0,0 +1 @@ +gcc -o libHelloWorld.so -shared libHelloWorld.c diff --git a/1_hello_world/napi/example2/libHelloWorld/lib/libHelloWorld.c b/1_hello_world/napi/example2/libHelloWorld/lib/libHelloWorld.c new file mode 100644 index 00000000..fb384197 --- /dev/null +++ b/1_hello_world/napi/example2/libHelloWorld/lib/libHelloWorld.c @@ -0,0 +1,10 @@ +#include "libHelloWorld.h" +#include + +char * HelloWorldConcat (char * cHello, char * cWorld){ + char * cHelloWorld = NULL; + + cHelloWorld = strcat(cHello, cWorld); + + return cHelloWorld; +} diff --git a/1_hello_world/napi/example2/libHelloWorld/lib/libHelloWorld.h b/1_hello_world/napi/example2/libHelloWorld/lib/libHelloWorld.h new file mode 100644 index 00000000..1594906f --- /dev/null +++ b/1_hello_world/napi/example2/libHelloWorld/lib/libHelloWorld.h @@ -0,0 +1,6 @@ +#ifndef __HELLOWORLDSDK_TYPES_H__ +#define __HELLOWORLDSDK_TYPES_H__ + +char * HelloWorldConcat (char * cHello, char * cWorld); + +#endif diff --git a/1_hello_world/napi/example2/libHelloWorld/module.js b/1_hello_world/napi/example2/libHelloWorld/module.js new file mode 100644 index 00000000..027e1798 --- /dev/null +++ b/1_hello_world/napi/example2/libHelloWorld/module.js @@ -0,0 +1,5 @@ +const addon = require('./build/Release/module'); +const hello = "Hello"; +const world = "World"; + +console.log(`${hello} concat ${world} equals`, addon.helloWorldConcat(hello, world)); diff --git a/1_hello_world/napi/example2/libHelloWorld/package.json b/1_hello_world/napi/example2/libHelloWorld/package.json new file mode 100644 index 00000000..f17105f2 --- /dev/null +++ b/1_hello_world/napi/example2/libHelloWorld/package.json @@ -0,0 +1,12 @@ +{ + "name": "helloworldlib", + "version": "1.0.0", + "description": "NAPI Test", + "main": "module.js", + "scripts": { + "start": "node-gyp configure build && node module.js", + "test": "console.log(\"Hello World!\");" + }, + "author": "Steven Klein", + "license": "MIT" +} diff --git a/1_hello_world/napi/example2/libHelloWorld/src/module.c b/1_hello_world/napi/example2/libHelloWorld/src/module.c new file mode 100644 index 00000000..cafc425b --- /dev/null +++ b/1_hello_world/napi/example2/libHelloWorld/src/module.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include "libHelloWorld.h" + +napi_value hello_world_concat (napi_env env, napi_callback_info info) { + + size_t argc = 2; + size_t iTotalSize = 0; + + napi_value args[2]; + + napi_get_cb_info(env, info, &argc, args, NULL, NULL); + + size_t str_size; + size_t str_size_read; + + napi_get_value_string_utf8(env, args[0], NULL, 0, &str_size); + char * cHello; + cHello = (char*)calloc(str_size + 1, sizeof(char)); + str_size = str_size + 1; + napi_get_value_string_utf8(env, args[0], cHello, str_size, &str_size_read); + + iTotalSize = iTotalSize + str_size_read; + + napi_get_value_string_utf8(env, args[1], NULL, 0, &str_size); + char * cWorld; + cWorld = (char*)calloc(str_size + 1, sizeof(char)); + str_size = str_size + 1; + napi_get_value_string_utf8(env, args[1], cWorld, str_size, &str_size_read); + + iTotalSize = iTotalSize + str_size_read; + + char * cResult = HelloWorldConcat(cHello, cWorld); + //printf("%s, %s \n", "Hello", cResult); // Debug output: Hello, world + + napi_value result; + + napi_create_string_utf8(env, cResult, iTotalSize, &result); + free(cHello); + free(cWorld); + return result; +} + +napi_value Init(napi_env env, napi_value exports) { + napi_status status; + napi_value fn; + + status = napi_create_function(env, NULL, 0, hello_world_concat, NULL, &fn); + if (status != napi_ok) { + napi_throw_error(env, NULL, "Unable to wrap native function"); + } + + status = napi_set_named_property(env, exports, "helloWorldConcat", fn); + if (status != napi_ok) { + napi_throw_error(env, NULL, "Unable to populate exports"); + } + + return exports; +} + +NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)