将v8对象转换为自定义的C ++对象

我目前正在开发一个nodejs模块,用C ++编写,我一直在寻找一种方法来将v8::Objectopencv转换成cv::Mat对象,现在没有任何运气。

我看到南图书馆可以帮助转换对象,但我不知道如何,我甚至不知道是否有可能在我的情况下转换它们。

v8果汁项目将满足我的期望,但由于它已被放弃,我只是不知道如何做到这一点。

这是我想要做的一个片段:

 void BRMatcher::run(const v8::FunctionCallbackInfo<v8::Value>& args) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope scope(isolate); if (args.Length() < 1) { isolate->ThrowException(v8::Exception::TypeError(v8::String::NewFromUtf8(isolate, "Missing parameter [Mat img]."))); return ; } if (!args[0]->IsObject()) { isolate->ThrowException(v8::Exception::TypeError(v8::String::NewFromUtf8(isolate, "Parameter [Mat img] must be an object."))); return ; } v8::Local<v8::Object> cvMat(args[0]->ToObject()); Mat img = ??? // This is where I ended up... // ... } 

在StackOverflow上讨论这个问题的所有post都是过时的(旧版本或者不再工作的工具)

所以我的问题是:如何将我收到的参数转换为cv::Mat对象? 我想要的任何types?

任何帮助将不胜感激,谢谢!

起初,我会build议看Node.js像node-opencv现有的openCV绑定。

如果您需要绑定C ++和JavaScript代码,则有几个库。 作为其中一个人的作者,我知道其他几个:

  • vu8 (废弃)
  • v8果汁 (废弃)
  • 脚本bindng在cpgf
  • Embind

据我所知,要将C ++对象转换为v8 :: Object,所有这些对象都使用v8::Object::SetAlignedPointerInInternalField()函数。

C ++对象到v8::Object转换通常通过将C ++指针映射到映射容器中的V8对象的持久句柄来执行。

看看Nodejs.org C ++插件和Nan教程。 虽然两者都有点误导,但它们无论如何都描述了规范的方式。 使用Nan比直接的V8 API,因为特别是这部分(过去和现在)正在改变很多。

随着Nan你正在寻找传递包装对象 。 更确切地说,这条线是它的核心。

在Node-OpenCV的 这个分支中,我正在用cv::Mat来完成这个工作,以使它成为JS-land的第一个类对象。 也许这个实现可能会帮助你。

TL; DR

Nan::ObjectWrap包装对象并传递它。 内部使用v8::SetInternalFieldPointer(); 为你。 这基本上是复制粘贴。

 // lib/mat.js var cv = require('./bindings')('addon'); function Mat() { } /** * returns the wrapped c++ object * [arguments optional] */ Mat.prototype.createMat = function (a) { var args = Array.prototype.slice.call(arguments); return cv.Mat.createMat(args[0]) } 
 // src/addon.cc // just initializes all your modules. Magic happening in mat.h and matwrap.h // matwrap.cc is the implementation of the wrapped object. mat.cc holds // JS-libarary specific methods #include <nan.h> #include "opencv.h" #include "imgproc.h" #include "mat.h" #include "matwrap.h" void InitAll(v8::Local<v8::Object> exports) { Opencv::Init(exports); ImgProc::Init(exports); Matwrap::Init(); Mat::Init(exports); } NODE_MODULE(addon, InitAll) 

这里重要的东西

 // src/matwrap.h #ifndef MATWRAP_H #define MATWRAP_H #include <opencv2/opencv.hpp> #include <nan.h> class Matwrap : public Nan::ObjectWrap { public: static void Init(); static v8::Local<v8::Object> NewInstance(v8::Local<v8::Value> arg); cv::Mat Val() const { return val_; } private: Matwrap(); ~Matwrap(); static Nan::Persistent<v8::Function> constructor; static void New(const Nan::FunctionCallbackInfo<v8::Value>& info); cv::Mat val_; }; #endif 

在这里你正在包装它(基本就是这样,按照下面的消费):

 // src/matwrap.cc #include <node.h> #include "matwrap.h" #include <opencv2/opencv.hpp> Matwrap::Matwrap() {}; Matwrap::~Matwrap() {}; Nan::Persistent<v8::Function> Matwrap::constructor; void Matwrap::Init() { Nan::HandleScope scope; // Prepare constructor template v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New); tpl->SetClassName(Nan::New("Matwrap").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); constructor.Reset(tpl->GetFunction()); } void Matwrap::New(const Nan::FunctionCallbackInfo<v8::Value>& info) { // wrap it... Matwrap* obj = new Matwrap(); cv::Mat src; obj->val_ = src; obj->Wrap(info.This()); // return wrapped here... info.GetReturnValue().Set(info.This()); } v8::Local<v8::Object> Matwrap::NewInstance(v8::Local<v8::Value> arg) { Nan::EscapableHandleScope scope; // const unsigned argc = 1; // v8::Local<v8::Value> argv[argc] = { arg }; v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor); v8::Local<v8::Object> instance = cons->NewInstance(); return scope.Escape(instance); } 

为了消费,你可以做这样的事情:

 // lib/mat.js /** * Returns true if the array has no elements. * @param {Object} mat - native cv::Mat * @return {Boolean} */ Mat.prototype.empty = function (mat) { var args = Array.prototype.slice.call(arguments); return cv.Mat.empty(args[0]) } 
 // src/mat.h // This is your API #ifndef MAT_H #define MAT_H // #include <opencv2/opencv.hpp> #include <nan.h> class Mat : public Nan::ObjectWrap { public: static void Init(v8::Local<v8::Object> exports); private: explicit Mat(double value = 0); ~Mat(); static void New(const Nan::FunctionCallbackInfo<v8::Value>& info); static void CreateMat(const Nan::FunctionCallbackInfo<v8::Value>& info); static void Empty(const Nan::FunctionCallbackInfo<v8::Value>& info); static void Total(const Nan::FunctionCallbackInfo<v8::Value>& info); static void Type(const Nan::FunctionCallbackInfo<v8::Value>& info); static Nan::Persistent<v8::Function> constructor; double value_; }; #endif 
 // src/mat.cc #include "mat.h" #include "matwrap.h" #include <opencv2/opencv.hpp> Nan::Persistent<v8::Function> Mat::constructor; Mat::Mat(double value) : value_(value) { } Mat::~Mat() { } void Mat::Init(v8::Local<v8::Object> exports) { Nan::HandleScope scope; // Prepare constructor template v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New); tpl->SetClassName(Nan::New("Mat").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); // Prototype Nan::SetPrototypeMethod(tpl, "createMat", CreateMat); Nan::SetPrototypeMethod(tpl, "empty", Empty); Nan::SetPrototypeMethod(tpl, "total", Total); Nan::SetPrototypeMethod(tpl, "type", Type); constructor.Reset(tpl->GetFunction()); exports->Set(Nan::New("Mat").ToLocalChecked(), tpl->GetFunction()); } void Mat::New(const Nan::FunctionCallbackInfo<v8::Value>& info) { if (info.IsConstructCall()) { // Invoked as constructor: `new Opencv(...)` double value = info[0]->IsUndefined() ? 0 : info[0]->NumberValue(); Mat* obj = new Mat(value); obj->Wrap(info.This()); info.GetReturnValue().Set(info.This()); } else { // Invoked as plain function `Opencv(...)`, turn into construct call. const int argc = 1; v8::Local<v8::Value> argv[argc] = { info[0] }; v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor); info.GetReturnValue().Set(cons->NewInstance(argc, argv)); } } void Mat::CreateMat(const Nan::FunctionCallbackInfo<v8::Value>& info) { info.GetReturnValue().Set(Matwrap::NewInstance(info[0])); } void Mat::Empty(const Nan::FunctionCallbackInfo<v8::Value>& info) { Matwrap* obj = Nan::ObjectWrap::Unwrap<Matwrap>(info[0]->ToObject()); // check through cv::Mat::empty() if (obj->Val().empty()) { // return JS bool info.GetReturnValue().Set(Nan::True()); } else { // TODO: logically not correct info.GetReturnValue().Set(Nan::False()); } }