Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

object_wrappers.md 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. ## Object Wrappers
  2. The `ObjectWrap` class can be used to make wrapped C++ objects and a factory of wrapped objects.
  3. - <a href="#api_nan_object_wrap"><b><code>Nan::ObjectWrap</code></b></a>
  4. <a name="api_nan_object_wrap"></a>
  5. ### Nan::ObjectWrap()
  6. A reimplementation of `node::ObjectWrap` that adds some API not present in older versions of Node. Should be preferred over `node::ObjectWrap` in all cases for consistency.
  7. Definition:
  8. ```c++
  9. class ObjectWrap {
  10. public:
  11. ObjectWrap();
  12. virtual ~ObjectWrap();
  13. template <class T>
  14. static inline T* Unwrap(v8::Local<v8::Object> handle);
  15. inline v8::Local<v8::Object> handle();
  16. inline Nan::Persistent<v8::Object>& persistent();
  17. protected:
  18. inline void Wrap(v8::Local<v8::Object> handle);
  19. inline void MakeWeak();
  20. /* Ref() marks the object as being attached to an event loop.
  21. * Refed objects will not be garbage collected, even if
  22. * all references are lost.
  23. */
  24. virtual void Ref();
  25. /* Unref() marks an object as detached from the event loop. This is its
  26. * default state. When an object with a "weak" reference changes from
  27. * attached to detached state it will be freed. Be careful not to access
  28. * the object after making this call as it might be gone!
  29. * (A "weak reference" means an object that only has a
  30. * persistant handle.)
  31. *
  32. * DO NOT CALL THIS FROM DESTRUCTOR
  33. */
  34. virtual void Unref();
  35. int refs_; // ro
  36. };
  37. ```
  38. See the Node documentation on [Wrapping C++ Objects](https://nodejs.org/api/addons.html#addons_wrapping_c_objects) for more details.
  39. ### This vs. Holder
  40. When calling `Unwrap`, it is important that the argument is indeed some JavaScript object which got wrapped by a `Wrap` call for this class or any derived class.
  41. The `Signature` installed by [`Nan::SetPrototypeMethod()`](methods.md#api_nan_set_prototype_method) does ensure that `info.Holder()` is just such an instance.
  42. In Node 0.12 and later, `info.This()` will also be of such a type, since otherwise the invocation will get rejected.
  43. However, in Node 0.10 and before it was possible to invoke a method on a JavaScript object which just had the extension type in its prototype chain.
  44. In such a situation, calling `Unwrap` on `info.This()` will likely lead to a failed assertion causing a crash, but could lead to even more serious corruption.
  45. On the other hand, calling `Unwrap` in an [accessor](methods.md#api_nan_set_accessor) should not use `Holder()` if the accessor is defined on the prototype.
  46. So either define your accessors on the instance template,
  47. or use `This()` after verifying that it is indeed a valid object.
  48. ### Examples
  49. #### Basic
  50. ```c++
  51. class MyObject : public Nan::ObjectWrap {
  52. public:
  53. static NAN_MODULE_INIT(Init) {
  54. v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
  55. tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());
  56. tpl->InstanceTemplate()->SetInternalFieldCount(1);
  57. Nan::SetPrototypeMethod(tpl, "getHandle", GetHandle);
  58. Nan::SetPrototypeMethod(tpl, "getValue", GetValue);
  59. constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
  60. Nan::Set(target, Nan::New("MyObject").ToLocalChecked(),
  61. Nan::GetFunction(tpl).ToLocalChecked());
  62. }
  63. private:
  64. explicit MyObject(double value = 0) : value_(value) {}
  65. ~MyObject() {}
  66. static NAN_METHOD(New) {
  67. if (info.IsConstructCall()) {
  68. double value = info[0]->IsUndefined() ? 0 : Nan::To<double>(info[0]).FromJust();
  69. MyObject *obj = new MyObject(value);
  70. obj->Wrap(info.This());
  71. info.GetReturnValue().Set(info.This());
  72. } else {
  73. const int argc = 1;
  74. v8::Local<v8::Value> argv[argc] = {info[0]};
  75. v8::Local<v8::Function> cons = Nan::New(constructor());
  76. info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked());
  77. }
  78. }
  79. static NAN_METHOD(GetHandle) {
  80. MyObject* obj = Nan::ObjectWrap::Unwrap<MyObject>(info.Holder());
  81. info.GetReturnValue().Set(obj->handle());
  82. }
  83. static NAN_METHOD(GetValue) {
  84. MyObject* obj = Nan::ObjectWrap::Unwrap<MyObject>(info.Holder());
  85. info.GetReturnValue().Set(obj->value_);
  86. }
  87. static inline Nan::Persistent<v8::Function> & constructor() {
  88. static Nan::Persistent<v8::Function> my_constructor;
  89. return my_constructor;
  90. }
  91. double value_;
  92. };
  93. NODE_MODULE(objectwrapper, MyObject::Init)
  94. ```
  95. To use in Javascript:
  96. ```Javascript
  97. var objectwrapper = require('bindings')('objectwrapper');
  98. var obj = new objectwrapper.MyObject(5);
  99. console.log('Should be 5: ' + obj.getValue());
  100. ```
  101. #### Factory of wrapped objects
  102. ```c++
  103. class MyFactoryObject : public Nan::ObjectWrap {
  104. public:
  105. static NAN_MODULE_INIT(Init) {
  106. v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
  107. tpl->InstanceTemplate()->SetInternalFieldCount(1);
  108. Nan::SetPrototypeMethod(tpl, "getValue", GetValue);
  109. constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
  110. }
  111. static NAN_METHOD(NewInstance) {
  112. v8::Local<v8::Function> cons = Nan::New(constructor());
  113. double value = info[0]->IsNumber() ? Nan::To<double>(info[0]).FromJust() : 0;
  114. const int argc = 1;
  115. v8::Local<v8::Value> argv[1] = {Nan::New(value)};
  116. info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked());
  117. }
  118. // Needed for the next example:
  119. inline double value() const {
  120. return value_;
  121. }
  122. private:
  123. explicit MyFactoryObject(double value = 0) : value_(value) {}
  124. ~MyFactoryObject() {}
  125. static NAN_METHOD(New) {
  126. if (info.IsConstructCall()) {
  127. double value = info[0]->IsNumber() ? Nan::To<double>(info[0]).FromJust() : 0;
  128. MyFactoryObject * obj = new MyFactoryObject(value);
  129. obj->Wrap(info.This());
  130. info.GetReturnValue().Set(info.This());
  131. } else {
  132. const int argc = 1;
  133. v8::Local<v8::Value> argv[argc] = {info[0]};
  134. v8::Local<v8::Function> cons = Nan::New(constructor());
  135. info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked());
  136. }
  137. }
  138. static NAN_METHOD(GetValue) {
  139. MyFactoryObject* obj = ObjectWrap::Unwrap<MyFactoryObject>(info.Holder());
  140. info.GetReturnValue().Set(obj->value_);
  141. }
  142. static inline Nan::Persistent<v8::Function> & constructor() {
  143. static Nan::Persistent<v8::Function> my_constructor;
  144. return my_constructor;
  145. }
  146. double value_;
  147. };
  148. NAN_MODULE_INIT(Init) {
  149. MyFactoryObject::Init(target);
  150. Nan::Set(target,
  151. Nan::New<v8::String>("newFactoryObjectInstance").ToLocalChecked(),
  152. Nan::GetFunction(
  153. Nan::New<v8::FunctionTemplate>(MyFactoryObject::NewInstance)).ToLocalChecked()
  154. );
  155. }
  156. NODE_MODULE(wrappedobjectfactory, Init)
  157. ```
  158. To use in Javascript:
  159. ```Javascript
  160. var wrappedobjectfactory = require('bindings')('wrappedobjectfactory');
  161. var obj = wrappedobjectfactory.newFactoryObjectInstance(10);
  162. console.log('Should be 10: ' + obj.getValue());
  163. ```
  164. #### Passing wrapped objects around
  165. Use the `MyFactoryObject` class above along with the following:
  166. ```c++
  167. static NAN_METHOD(Sum) {
  168. Nan::MaybeLocal<v8::Object> maybe1 = Nan::To<v8::Object>(info[0]);
  169. Nan::MaybeLocal<v8::Object> maybe2 = Nan::To<v8::Object>(info[1]);
  170. // Quick check:
  171. if (maybe1.IsEmpty() || maybe2.IsEmpty()) {
  172. // return value is undefined by default
  173. return;
  174. }
  175. MyFactoryObject* obj1 =
  176. Nan::ObjectWrap::Unwrap<MyFactoryObject>(maybe1.ToLocalChecked());
  177. MyFactoryObject* obj2 =
  178. Nan::ObjectWrap::Unwrap<MyFactoryObject>(maybe2.ToLocalChecked());
  179. info.GetReturnValue().Set(Nan::New<v8::Number>(obj1->value() + obj2->value()));
  180. }
  181. NAN_MODULE_INIT(Init) {
  182. MyFactoryObject::Init(target);
  183. Nan::Set(target,
  184. Nan::New<v8::String>("newFactoryObjectInstance").ToLocalChecked(),
  185. Nan::GetFunction(
  186. Nan::New<v8::FunctionTemplate>(MyFactoryObject::NewInstance)).ToLocalChecked()
  187. );
  188. Nan::Set(target,
  189. Nan::New<v8::String>("sum").ToLocalChecked(),
  190. Nan::GetFunction(Nan::New<v8::FunctionTemplate>(Sum)).ToLocalChecked()
  191. );
  192. }
  193. NODE_MODULE(myaddon, Init)
  194. ```
  195. To use in Javascript:
  196. ```Javascript
  197. var myaddon = require('bindings')('myaddon');
  198. var obj1 = myaddon.newFactoryObjectInstance(5);
  199. var obj2 = myaddon.newFactoryObjectInstance(10);
  200. console.log('sum of object values: ' + myaddon.sum(obj1, obj2));
  201. ```