Skip to content

Node.js native module programming

bellbind edited this page Oct 13, 2013 · 11 revisions

Separate application algorithm codes and Node.js plug codes

  • Application codes should be removed any node.js and v8 related definitions.
    • it can use another languages for application code. e.g. C, Objective-C
  • Node.js plug codes are almost for convert arguments and result.

About v8 Handles

3 Handle (smart pointer) type exists

  • Handle: as smart pointer of RAII (release the holding resource by its destructor)
  • Local: automatically managed by HandleScope
  • Persistent: explicitly call Dispose() to release

HandleScope instance is stacked memory manager for Local handle.

  • HandleScope scope: make scope upon top of HandleScope stack.
  • Local<...> v = ...: managed by stack top scope. the scope destructor release all managed handle
  • return scope.Close(localHandle): unmanage a localHandle object on the scope, then return localHandle as Handle

Convert C type to v8::Value

  • char* => String: String::New(s) or String::NewSymbol(s)
  • String => char*: String::Utf8Value utf8(str); char* s = *utf8;
  • int32_t => Integer: Integer::New(i)
  • Integer => int32_t: v->Int32Value()
  • uint32_t => Integer: Integer::NewFromUnsigned(i)
  • Integer => uint32_t: v->Uint32Value()

Keep Handle of C object in v8 Object

    auto clazz = v8::FunctionTemplate::New(New);
    clazz->InstanceTemplate()->SetInternalFieldCount(1);

n of SetInternalFieldCount(n) is field count of ObjectWrap or count of use SetInernalField(i, v)

Watching fd by uv_poll pattern

  // prepare data struct for holding objects used in callback process
  struct CallbackData {
    Persistent<Object> thisObj;
    Persistent<Function> callback;
  };
  
  void callbackByUv(uv_poll_t* handle, int status, int events) {
    HandleScope scope;
    auto data = static_cast<CallbackData*>(handle->data); // get user data
    uv_poll_stop(handle); // stop poll
    // handle should delete in close callback (after closed)
    // DON'T delete in uv callback!!
    uv_close(reinterpret_cast<uv_handle_t*>(handle), 
             [](uv_handle_t* handle) -> void {delete handle;}); 

    callbackCall(data); //e.g. do action for fd, then call callback by action result
    
    // destroy callback data
    data->thisObj.Dispose();
    data->callback.Dispose();
    delete data;
  }
  
  Handle<Value> method(const Arguments& args) {
    HandleScope scope;
    // prepare data used in the uv callback (after polled)
    auto data = new CallbackData;
    auto thisObj = args.This();
    data->thisObj = Persistent<Object>::New(thisObj);
    data->callback = Persistent<Function>::New(args[0].As<Function>());
    
    int fd = acquireFd(thisObj); // get fd from Object

    // poll fd
    uv_poll_t* handle = new uv_poll_t;
    handle->data = data;
    uv_poll_init(uv_default_loop(), handle, fd);
    uv_poll_start(handle, UV_READABLE, callbackByUv); // set callback

    return v8::Undefined();
  }
Clone this wiki locally