fengmk2 / fengmk2.github.com

MK2's github pages

Home Page:http://fengmk2.github.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

nan 入门手册

fengmk2 opened this issue · comments

最近在尝试改进 hsf 的 c++ 模块实现, 将 hessian 1.0 的 encode 和 decode 暴露出来给 js 调用.

因为需要保证 hsf 模块能在node 0.10.x 和 0.11.x 都能正常使用, 那么必须让此 c++ 模块有良好的代码兼容性.

吐血, c++ 新手还要考虑兼容性, 晴天霹雳.

org, 还好发现了 nan: A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10 and 0.11, and eventually 0.12.

示例代码

@see nan#api

codes at: nan-example

基本类型

// function showTypes() {}
NAN_METHOD(showTypes) {
  NanScope();

  // var foo;
  // var bar = null;
  v8::Local<v8::Value> foo = NanUndefined();
  v8::Local<v8::Value> bar = NanNull();
  v8::Handle<v8::Value> bar2 = NanNull();

  // var t = true;
  // var f = false;
  v8::Local<v8::Boolean> t = NanTrue();
  v8::Local<v8::Boolean> f = NanFalse();

  // var v1 = 100;
  // var v2 = 1024.123;
  // var v3 = 0.123456789;
  v8::Local<v8::Number> v1 = NanNew<v8::Number>(100);
  v8::Local<v8::Number> v2 = NanNew<v8::Number>(1024.123);
  v8::Handle<v8::Number> v3 = NanNew<v8::Number>(0.123456789);

  // var s1 = '';
  // var s2 = 'hello world';
  // var s3 = 'no ascii 还有中文';
  v8::Local<v8::String> s1 = NanNew<v8::String>("");
  v8::Local<v8::String> s2 = NanNew<v8::String>("hello world");
  v8::Local<v8::String> s3 = NanNew<v8::String>("no ascii 还有中文");

  // var now = new Date(1399273631054);
  double timestamp = 1399273631054;
  v8::Local<v8::Date> now = NanNew<v8::Date>(timestamp);

  // var result = {};
  // result['undefined'] = foo;
  // result['null'] = bar;
  // result['null2'] = bar2;
  // result['true'] = t;
  // result['false'] = f;
  // result['v1'] = v1;
  // result['v2'] = v2;
  // result['v3'] = v3;
  // result['s1'] = s1;
  // result['s2'] = s2;
  // result['s3'] = s3;
  // result.now = now;
  v8::Local<v8::Object> result = NanNew<v8::Object>();
  result->Set(NanSymbol("undefined"), foo);
  result->Set(NanSymbol("null"), bar);
  result->Set(NanSymbol("null2"), bar2);
  result->Set(NanSymbol("true"), t);
  result->Set(NanSymbol("false"), f);
  result->Set(NanSymbol("v1"), v1);
  result->Set(NanSymbol("v2"), v2);
  result->Set(NanSymbol("v3"), v3);
  result->Set(NanSymbol("s1"), s1);
  result->Set(NanSymbol("s2"), s2);
  result->Set(NanSymbol("s3"), s3);
  result->Set(NanSymbol("now"), now);

  // var arr = [];
  // arr.push(foo);
  // arr.push(bar);
  // arr.push(bar2);
  // arr.push(t);
  // arr.push(f);
  // arr.push(v1);
  // arr.push(v2);
  // arr.push(v3);
  // arr.push(s1);
  // arr.push(s2);
  // arr.push(s3);
  // arr.push(now);
  int index = 0;
  v8::Local<v8::Array> arr = NanNew<v8::Array>();
  arr->Set(index++, foo);
  arr->Set(index++, bar);
  arr->Set(index++, bar2);
  arr->Set(index++, t);
  arr->Set(index++, f);
  arr->Set(index++, v1);
  arr->Set(index++, v2);
  arr->Set(index++, v3);
  arr->Set(index++, s1);
  arr->Set(index++, s2);
  arr->Set(index++, s3);
  arr->Set(index++, now);

  result->Set(NanSymbol("array"), arr);
  result->Set(NanSymbol("array-length"), NanNew<v8::Number>(arr->Length()));

  NanReturnValue(result);
}

v8::Local 和 v8::Handle 的区别

v8::XXX 和 v8::XXXObject 的区别

Number vs NumberObject

函数

module.exports

/**
 * A JavaScript object (ECMA-262, 4.3.3)
 */
class V8_EXPORT Object : public Value {
 public:
  bool Set(Handle<Value> key,
           Handle<Value> value,
           PropertyAttribute attribs = None);

  bool Set(uint32_t index, Handle<Value> value);

  // Sets a local property on this object bypassing interceptors and
  // overriding accessors or read-only properties.
  //
  // Note that if the object has an interceptor the property will be set
  // locally, but since the interceptor takes precedence the local property
  // will only be returned if the interceptor doesn't return a value.
  //
  // Note also that this only works for named properties.
  bool ForceSet(Handle<Value> key,
                Handle<Value> value,
                PropertyAttribute attribs = None);

  Local<Value> Get(Handle<Value> key);

  Local<Value> Get(uint32_t index);

  /**
   * Gets the property attributes of a property which can be None or
   * any combination of ReadOnly, DontEnum and DontDelete. Returns
   * None when the property doesn't exist.
   */
  PropertyAttribute GetPropertyAttributes(Handle<Value> key);

  bool Has(Handle<Value> key);

  bool Delete(Handle<Value> key);

  // Delete a property on this object bypassing interceptors and
  // ignoring dont-delete attributes.
  bool ForceDelete(Handle<Value> key);

  bool Has(uint32_t index);

  bool Delete(uint32_t index);

  bool SetAccessor(Handle<String> name,
                   AccessorGetterCallback getter,
                   AccessorSetterCallback setter = 0,
                   Handle<Value> data = Handle<Value>(),
                   AccessControl settings = DEFAULT,
                   PropertyAttribute attribute = None);

  // This function is not yet stable and should not be used at this time.
  bool SetDeclaredAccessor(Local<String> name,
                           Local<DeclaredAccessorDescriptor> descriptor,
                           PropertyAttribute attribute = None,
                           AccessControl settings = DEFAULT);

  void SetAccessorProperty(Local<String> name,
                           Local<Function> getter,
                           Handle<Function> setter = Handle<Function>(),
                           PropertyAttribute attribute = None,
                           AccessControl settings = DEFAULT);

  /**
   * Functionality for private properties.
   * This is an experimental feature, use at your own risk.
   * Note: Private properties are inherited. Do not rely on this, since it may
   * change.
   */
  bool HasPrivate(Handle<Private> key);
  bool SetPrivate(Handle<Private> key, Handle<Value> value);
  bool DeletePrivate(Handle<Private> key);
  Local<Value> GetPrivate(Handle<Private> key);

  /**
   * Returns an array containing the names of the enumerable properties
   * of this object, including properties from prototype objects.  The
   * array returned by this method contains the same values as would
   * be enumerated by a for-in statement over this object.
   */
  Local<Array> GetPropertyNames();

  /**
   * This function has the same functionality as GetPropertyNames but
   * the returned array doesn't contain the names of properties from
   * prototype objects.
   */
  Local<Array> GetOwnPropertyNames();

  /**
   * Get the prototype object.  This does not skip objects marked to
   * be skipped by __proto__ and it does not consult the security
   * handler.
   */
  Local<Value> GetPrototype();

  /**
   * Set the prototype object.  This does not skip objects marked to
   * be skipped by __proto__ and it does not consult the security
   * handler.
   */
  bool SetPrototype(Handle<Value> prototype);

  /**
   * Finds an instance of the given function template in the prototype
   * chain.
   */
  Local<Object> FindInstanceInPrototypeChain(Handle<FunctionTemplate> tmpl);

  /**
   * Call builtin Object.prototype.toString on this object.
   * This is different from Value::ToString() that may call
   * user-defined toString function. This one does not.
   */
  Local<String> ObjectProtoToString();

  /**
   * Returns the function invoked as a constructor for this object.
   * May be the null value.
   */
  Local<Value> GetConstructor();

  /**
   * Returns the name of the function invoked as a constructor for this object.
   */
  Local<String> GetConstructorName();

  /** Gets the number of internal fields for this Object. */
  int InternalFieldCount();

  /** Same as above, but works for Persistents */
  V8_INLINE static int InternalFieldCount(
      const PersistentBase<Object>& object) {
    return object.val_->InternalFieldCount();
  }

  /** Gets the value from an internal field. */
  V8_INLINE Local<Value> GetInternalField(int index);

  /** Sets the value in an internal field. */
  void SetInternalField(int index, Handle<Value> value);

  /**
   * Gets a 2-byte-aligned native pointer from an internal field. This field
   * must have been set by SetAlignedPointerInInternalField, everything else
   * leads to undefined behavior.
   */
  V8_INLINE void* GetAlignedPointerFromInternalField(int index);

  /** Same as above, but works for Persistents */
  V8_INLINE static void* GetAlignedPointerFromInternalField(
      const PersistentBase<Object>& object, int index) {
    return object.val_->GetAlignedPointerFromInternalField(index);
  }

  /**
   * Sets a 2-byte-aligned native pointer in an internal field. To retrieve such
   * a field, GetAlignedPointerFromInternalField must be used, everything else
   * leads to undefined behavior.
   */
  void SetAlignedPointerInInternalField(int index, void* value);

  // Testers for local properties.
  bool HasOwnProperty(Handle<String> key);
  bool HasRealNamedProperty(Handle<String> key);
  bool HasRealIndexedProperty(uint32_t index);
  bool HasRealNamedCallbackProperty(Handle<String> key);

  /**
   * If result.IsEmpty() no real property was located in the prototype chain.
   * This means interceptors in the prototype chain are not called.
   */
  Local<Value> GetRealNamedPropertyInPrototypeChain(Handle<String> key);

  /**
   * If result.IsEmpty() no real property was located on the object or
   * in the prototype chain.
   * This means interceptors in the prototype chain are not called.
   */
  Local<Value> GetRealNamedProperty(Handle<String> key);

  /** Tests for a named lookup interceptor.*/
  bool HasNamedLookupInterceptor();

  /** Tests for an index lookup interceptor.*/
  bool HasIndexedLookupInterceptor();

  /**
   * Turns on access check on the object if the object is an instance of
   * a template that has access check callbacks. If an object has no
   * access check info, the object cannot be accessed by anyone.
   */
  void TurnOnAccessCheck();

  /**
   * Returns the identity hash for this object. The current implementation
   * uses a hidden property on the object to store the identity hash.
   *
   * The return value will never be 0. Also, it is not guaranteed to be
   * unique.
   */
  int GetIdentityHash();

  /**
   * Access hidden properties on JavaScript objects. These properties are
   * hidden from the executing JavaScript and only accessible through the V8
   * C++ API. Hidden properties introduced by V8 internally (for example the
   * identity hash) are prefixed with "v8::".
   */
  bool SetHiddenValue(Handle<String> key, Handle<Value> value);
  Local<Value> GetHiddenValue(Handle<String> key);
  bool DeleteHiddenValue(Handle<String> key);

  /**
   * Returns true if this is an instance of an api function (one
   * created from a function created from a function template) and has
   * been modified since it was created.  Note that this method is
   * conservative and may return true for objects that haven't actually
   * been modified.
   */
  bool IsDirty();

  /**
   * Clone this object with a fast but shallow copy.  Values will point
   * to the same values as the original object.
   */
  Local<Object> Clone();

  /**
   * Returns the context in which the object was created.
   */
  Local<Context> CreationContext();

  /**
   * Set the backing store of the indexed properties to be managed by the
   * embedding layer. Access to the indexed properties will follow the rules
   * spelled out in CanvasPixelArray.
   * Note: The embedding program still owns the data and needs to ensure that
   *       the backing store is preserved while V8 has a reference.
   */
  void SetIndexedPropertiesToPixelData(uint8_t* data, int length);
  bool HasIndexedPropertiesInPixelData();
  uint8_t* GetIndexedPropertiesPixelData();
  int GetIndexedPropertiesPixelDataLength();

  /**
   * Set the backing store of the indexed properties to be managed by the
   * embedding layer. Access to the indexed properties will follow the rules
   * spelled out for the CanvasArray subtypes in the WebGL specification.
   * Note: The embedding program still owns the data and needs to ensure that
   *       the backing store is preserved while V8 has a reference.
   */
  void SetIndexedPropertiesToExternalArrayData(void* data,
                                               ExternalArrayType array_type,
                                               int number_of_elements);
  bool HasIndexedPropertiesInExternalArrayData();
  void* GetIndexedPropertiesExternalArrayData();
  ExternalArrayType GetIndexedPropertiesExternalArrayDataType();
  int GetIndexedPropertiesExternalArrayDataLength();

  /**
   * Checks whether a callback is set by the
   * ObjectTemplate::SetCallAsFunctionHandler method.
   * When an Object is callable this method returns true.
   */
  bool IsCallable();

  /**
   * Call an Object as a function if a callback is set by the
   * ObjectTemplate::SetCallAsFunctionHandler method.
   */
  Local<Value> CallAsFunction(Handle<Value> recv,
                              int argc,
                              Handle<Value> argv[]);

  /**
   * Call an Object as a constructor if a callback is set by the
   * ObjectTemplate::SetCallAsFunctionHandler method.
   * Note: This method behaves like the Function::NewInstance method.
   */
  Local<Value> CallAsConstructor(int argc, Handle<Value> argv[]);

  static Local<Object> New(Isolate* isolate);

  V8_INLINE static Object* Cast(Value* obj);

 private:
  Object();
  static void CheckCast(Value* obj);
  Local<Value> SlowGetInternalField(int index);
  void* SlowGetAlignedPointerFromInternalField(int index);
};


/**
 * An instance of the built-in array constructor (ECMA-262, 15.4.2).
 */
class V8_EXPORT Array : public Object {
 public:
  uint32_t Length() const;

  /**
   * Clones an element at index |index|.  Returns an empty
   * handle if cloning fails (for any reason).
   */
  Local<Object> CloneElementAt(uint32_t index);

  /**
   * Creates a JavaScript array with the given length. If the length
   * is negative the returned array will have length 0.
   */
  static Local<Array> New(Isolate* isolate, int length = 0);

  V8_INLINE static Array* Cast(Value* obj);
 private:
  Array();
  static void CheckCast(Value* obj);
};