2014
Nov
25

網頁好讀版

In order to be compatible for any version of Node.js and io.js. We can use the Nan library: " https://github.com/nodejs/nan "

If you have used the old version of Nan and want to upgrade it, you should do the following changes.

Nan Conversion
  1. // The Legacy Nan example
  2. unsigned int microSeconds = args[0]->Uint32Value();
  3. NanReturnValue(NanNew<String>("text"));
  4. NanReturnThis();
  5. Handle<Value> key = Nan::New<String>("DOMDocument");
  6. NODE_SET_PROTOTYPE_METHOD(constructor, "load", load);
  7.  
  8. // The latest Nan example
  9. unsigned int microSeconds = info[0]->Uint32Value();
  10. info.GetReturnValue().Set(Nan::New<String>("text"));
  11. info.GetReturnValue().Set(info.This());
  12. Handle<Value> key = Nan::New<String>("DOMDocument").ToLocalChecked();
  13. Nan::SetPrototypeMethod(constructor, "load", load);

After that here has more variable conversions for you.

Brief
  1. String::Utf8Value cmd(info[0]);
  2. unsigned int len = info[0]->Uint32Value();
  3. bool isBinary = info[0]->BooleanValue();
  4.  
  5. Local<Object> bufferObj = info[1]->ToObject();
  6. char* msg = Buffer::Data(bufferObj);

Pass a JavaScript string into native C/C++ with Nan library

Example
  1. #include <iostream>
  2. #include <node.h>
  3. #include <nan.h>
  4. using namespace std;
  5. using namespace v8;
  6. using namespace nan;
  7.  
  8. NAN_METHOD(name)
  9. {
  10. Nan::HandleScope scope;
  11. String::Utf8Value cmd(info[0]);
  12. string s = string(*cmd);
  13. info.GetReturnValue().Set(Nan::New<String>(s.c_str()).ToLocalChecked());
  14. }

Pass a JavaScript integer into native C/C++ with Nan library

Example
  1. #include <iostream>
  2. #include <node.h>
  3. #include <nan.h>
  4. using namespace std;
  5. using namespace v8;
  6. using namespace nan;
  7.  
  8. NAN_METHOD(name)
  9. {
  10. Nan::HandleScope scope;
  11. unsigned int len = info[0]->Uint32Value();
  12. info.GetReturnValue().Set(Nan::New<Integer>(len).ToLocalChecked());
  13. }

Pass a Node.js binary string into native C/C++ with Nan library

When you have Unicode String which include some un-English letters. Then you must pass the value in a binary format.

Example
  1. #include <iostream>
  2. #include <node.h>
  3. #include <nan.h>
  4. using namespace std;
  5. using namespace v8;
  6. using namespace nan;
  7.  
  8. NAN_METHOD(sendData)
  9. {
  10. Local<Object> bufferObj = info[0]->ToObject();
  11. unsigned int len = info[1]->Uint32Value();
  12. char* msg = Buffer::Data(bufferObj);
  13.  
  14. info.GetReturnValue().Set(Nan::New<String>(msg, len).ToLocalChecked());
  15. // You can not use strlen(msg). Because it is a binary not a string. The end of string is a null byte and the end of binary data is not null.
  16. }
Node.js call native function.
  1. //
  2. var data = "The data include some UTF8 encoding string.";
  3. length = Buffer.byteLength(data); //UTF8 length
  4. var buf = new Buffer(length);
  5. buf.write(data, 0, 'UTF8');
  6. native.sendData(buf, length);

Pass a JavaScript array into native C/C++ with Nan library

Pass array and return array
  1. NAN_METHOD(passArray) {
  2. Nan::HandleScope scope;
  3. vector<string> result;
  4. Handle<Value> val;
  5. Local<Array> arr = Nan::New<Array>();
  6.  
  7. if (info[0]->IsArray()) {
  8. Handle<Array> jsArray = Handle<Array>::Cast(info[0]);
  9. for (unsigned int i = 0; i < jsArray->Length(); i++) {
  10. val = jsArray->Get(i);
  11. result.push_back(string(*String::Utf8Value(val)));
  12. Nan::Set(arr, i, val);
  13. }
  14. }
  15. info.GetReturnValue().Set(arr);
  16. }

Pass a function into native C/C++ with Nan library

callback.cc
  1. #include <node.h>
  2. #include <nan.h>
  3. using namespace node;
  4. using namespace v8;
  5.  
  6. NAN_METHOD(runCallback) {
  7. Nan::HandleScope scope;
  8. Local<Object> context = Local<Object>::Cast(info[0]);
  9. Handle<Value> param1 = Handle<Value>::Cast(info[1]);
  10. Local<v8::Function > callback_handle = Local<v8::Function>::Cast(info[2]);
  11.  
  12. Local<Value> argv[1] = { param1 };
  13. Nan::MakeCallback(context, callback_handle, 1, argv);
  14. info.GetReturnValue().SetUndefined();
  15. }
  16.  
  17. void init (Handle<Object> target){
  18. Nan::HandleScope scope;
  19. Nan::SetMethod(target, "runCallback", runCallback);
  20. }
  21.  
  22. NODE_MODULE(obj, init)

After the success of compiling, then you can write a Node.js code to test the native shared object.

call.js
  1. var native = require('./build/Release/callback.node');
  2.  
  3. function person() {
  4. this.age = 18;
  5. }
  6.  
  7. person.prototype.run = function () {console.log("My age is " + this.age);};
  8.  
  9. var p = new person();
  10. p.age = 20;
  11.  
  12. native.runCallback(
  13. p, "the value",
  14. function (param1) {
  15. this.run();
  16. console.log("param1 = " + param1);
  17. }
  18. );

How to return "this" context

Example
  1. info.GetReturnValue().Set(info.This());

Examples

You can see more examples at my Node.js library called phplike.



Old Version of Nan library

Please migrate your legacy code to support the latest version of Nan library as soon as possibile.

The following is only used for the old version of Node.js 0.10.x. Node.js have already upgrade the latest JavaScript V8 engine. And we will used the new code to write a Node.js addon as stated previous paragraph.


Pass a JavaScript string into C/C++

Example
  1. #include <iostream>
  2. #include "v8.h"
  3. #include <string>
  4. using namespace std;
  5. using namespace v8;
  6.  
  7. Handle<Value> passString(const Arguments& args)
  8. {
  9. String::Utf8Value cmd(args[0]);
  10. string s = string(*cmd);
  11. return String::New(s.c_str());
  12. //Integer::New(1)
  13. }

Pass a JavaScript integer into C/C++

Example
  1. #include <iostream>
  2. #include "v8.h"
  3. #include <string>
  4. using namespace std;
  5. using namespace v8;
  6. Handle<Value> passInt(const Arguments& args)
  7. {
  8. unsigned int microSeconds = args[0]->Uint32Value();
  9.  
  10. return True();
  11. }

Pass a JavaScript array into C/C++

Example
  1. #include <iostream>
  2. #include "v8.h"
  3. #include "node.h"
  4. #include <string>
  5. #include <vector>
  6. using namespace std;
  7. using namespace v8;
  8. using namespace node;
  9.  
  10. Handle<Value> passArray(const Arguments& args) {
  11. vector<string> result;
  12. Handle<Value> val;
  13. if (args[0]->IsArray()) {
  14. Handle<Array> jsArray = Handle<Array>::Cast(arg[0]);
  15. for (int i = 0; i < jsArray->Length(); i++) {
  16. val = jsArray->Get(Integer::New(i));
  17. result.push_back(string(*String::Utf8Value(val)));
  18. }
  19. }
  20.  
  21. return String::New("success");
  22. }

Pass a JavaScript object into C/C++

Here is a example to get the value from a specific keyname and if this value is a function , we convert it into the variable type of v8 function Handle.

Example
  1. #include <iostream>
  2. #include "v8.h"
  3. #include "node.h"
  4. #include <string>
  5. using namespace std;
  6. using namespace v8;
  7. using namespace node;
  8.  
  9. Handle<Value> passObject(const Arguments& args) {
  10.  
  11. if (args[0]->IsObject()) {
  12. Handle<Object> object = Handle<Object>::Cast(args[0]);
  13. Handle<Value> fieldValue = object->Get(String::New("key1"));
  14. Handle<Value> callback = object->Get(String::New("callback"));
  15. if (callback->IsFunction()) {
  16. Handle<Function> fn = Handle<Function>::Cast(callback);
  17. }
  18. }
  19. }


Using the forloop to get every key and value from the object.

Example
  1. #include <iostream>
  2. #include "v8.h"
  3. #include "node.h"
  4. #include <string>
  5. #include <map>
  6. using namespace std;
  7. using namespace v8;
  8. using namespace node;
  9.  
  10. Handle<Value> passObject(const Arguments& args) {
  11. map<string, string> options;
  12. int i,n;
  13. if (args[0]->IsObject()) {
  14. jsOptions = Handle<Object>::Cast(args[0]);
  15. propertyNames = jsOptions->GetPropertyNames();
  16. n = propertyNames->Length();
  17. for (i = 0; i < n ; i++) {
  18. Handle<Value> b = propertyNames->Get(Integer::New(i));
  19. string c = string(*String::Utf8Value(b));
  20. Handle<Value> v = jsOptions->Get(b);
  21. options[c] = string(*String::Utf8Value(v));
  22. }
  23.  
  24. }
  25. }

Pass a JavaScript boolean into C/C++

Example
  1. #include <iostream>
  2. #include "v8.h"
  3. #include <string>
  4. using namespace std;
  5. using namespace v8;
  6. Handle<Value> passInt(const Arguments& args)
  7. {
  8. bool = args[0]->BooleanValue();
  9.  
  10. return bool;
  11. }

Pass a JavaScript binary into C/C++ char*

Example
  1. #include <iostream>
  2. #include "v8.h"
  3. #include <string>
  4. using namespace std;
  5. using namespace v8;
  6. Handle<Value> passBinary(const Arguments& args)
  7. {
  8. Local<Object> bufferObj = args[1]->ToObject();
  9. char* msg = Buffer::Data(bufferObj);
  10. }

Reference

網頁好讀版