Initial commit, demo program, wraps a C++ double in a JS object
authorNick Downing <downing.nick@gmail.com>
Thu, 4 Jan 2018 03:20:04 +0000 (14:20 +1100)
committerNick Downing <nick@ndcode.org>
Sun, 18 Nov 2018 02:37:55 +0000 (13:37 +1100)
.gitignore [new file with mode: 0644]
binding.gyp [new file with mode: 0644]
doc/C++ Addons _ Node.js v9.3.pdf [new file with mode: 0644]
env.sh [new file with mode: 0644]
n.sh [new file with mode: 0755]
test.js [new file with mode: 0755]
zetjs.cpp [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..4823a7c
--- /dev/null
@@ -0,0 +1,8 @@
+/build
+/index.map.0
+/index.param.0
+/index.v.0
+/index.vocab.0
+/nodesource_setup.sh
+/node_modules
+/package-lock.json
diff --git a/binding.gyp b/binding.gyp
new file mode 100644 (file)
index 0000000..900bb1f
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "targets": [
+    {
+      "target_name": "zet",
+      "sources": ["zetjs.cpp"]
+    }
+  ]
+}
diff --git a/doc/C++ Addons _ Node.js v9.3.pdf b/doc/C++ Addons _ Node.js v9.3.pdf
new file mode 100644 (file)
index 0000000..ef3ec17
Binary files /dev/null and b/doc/C++ Addons _ Node.js v9.3.pdf differ
diff --git a/env.sh b/env.sh
new file mode 100644 (file)
index 0000000..1bbcade
--- /dev/null
+++ b/env.sh
@@ -0,0 +1 @@
+PATH=`pwd`/node_modules/.bin:$PATH
diff --git a/n.sh b/n.sh
new file mode 100755 (executable)
index 0000000..5c1bfa4
--- /dev/null
+++ b/n.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+#sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10
+curl -sL https://deb.nodesource.com/setup_9.x -o nodesource_setup.sh
+sudo bash nodesource_setup.sh
+sudo apt-get install nodejs
+npm install node-gyp
diff --git a/test.js b/test.js
new file mode 100755 (executable)
index 0000000..bb35737
--- /dev/null
+++ b/test.js
@@ -0,0 +1,11 @@
+#!/usr/bin/env node
+
+const zet = require('./build/Release/zet');
+
+const obj = new zet.MyObject(10);
+console.log(obj.plusOne());
+// Prints: 11
+console.log(obj.plusOne());
+// Prints: 12
+console.log(obj.plusOne());
+// Prints: 13
diff --git a/zetjs.cpp b/zetjs.cpp
new file mode 100644 (file)
index 0000000..b87a4cf
--- /dev/null
+++ b/zetjs.cpp
@@ -0,0 +1,92 @@
+#include <node.h>
+#include <node_object_wrap.h>
+
+namespace zetjs {
+
+using v8::Context;
+using v8::Function;
+using v8::FunctionCallbackInfo;
+using v8::FunctionTemplate;
+using v8::Isolate;
+using v8::Local;
+using v8::Number;
+using v8::Object;
+using v8::Persistent;
+using v8::String;
+using v8::Value;
+
+class MyObject : public node::ObjectWrap {
+ public:
+  static void Init(v8::Local<v8::Object> exports);
+
+ private:
+  explicit MyObject(double value = 0);
+  ~MyObject();
+
+  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
+  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
+  static v8::Persistent<v8::Function> constructor;
+  double value_;
+};
+
+Persistent<Function> MyObject::constructor;
+
+MyObject::MyObject(double value) : value_(value) {
+}
+
+MyObject::~MyObject() {
+}
+
+void MyObject::Init(Local<Object> exports) {
+  Isolate* isolate = exports->GetIsolate();
+
+  // Prepare constructor template
+  Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
+  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
+  tpl->InstanceTemplate()->SetInternalFieldCount(1);
+
+  // Prototype
+  NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
+
+  constructor.Reset(isolate, tpl->GetFunction());
+  exports->Set(String::NewFromUtf8(isolate, "MyObject"),
+               tpl->GetFunction());
+}
+
+void MyObject::New(const FunctionCallbackInfo<Value>& args) {
+  Isolate* isolate = args.GetIsolate();
+
+  if (args.IsConstructCall()) {
+    // Invoked as constructor: `new MyObject(...)`
+    double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
+    MyObject* obj = new MyObject(value);
+    obj->Wrap(args.This());
+    args.GetReturnValue().Set(args.This());
+  } else {
+    // Invoked as plain function `MyObject(...)`, turn into construct call.
+    const int argc = 1;
+    Local<Value> argv[argc] = { args[0] };
+    Local<Context> context = isolate->GetCurrentContext();
+    Local<Function> cons = Local<Function>::New(isolate, constructor);
+    Local<Object> result =
+        cons->NewInstance(context, argc, argv).ToLocalChecked();
+    args.GetReturnValue().Set(result);
+  }
+}
+
+void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
+  Isolate* isolate = args.GetIsolate();
+
+  MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.Holder());
+  obj->value_ += 1;
+
+  args.GetReturnValue().Set(Number::New(isolate, obj->value_));
+}
+
+void InitAll(Local<Object> exports) {
+  MyObject::Init(exports);
+}
+
+NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll)
+
+}