es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Firmas de múltiples tipos de C++ N-API

Estoy aprendiendo C++ y experimentando con OpenCV y node-addon-api. Quería crear mi propio envoltorio para cv::Vec. docs


<h1>include <napi.h></h1> <h1>include <opencv2/core/matx.hpp></h1> class Vec : public Napi::ObjectWrap<Vec> { public: static Napi::Object Init(Napi::Env env, Napi::Object exports); explicit Vec(const Napi::CallbackInfo &info); private: static Napi::FunctionReference constructor; // // no type named 'Vec' in namespace 'cv'; // I would like this to be cv::Vec2 or cv::Vec3 ... of any type cv::Vec *<em>wrappedClass</em>; // duplicate member '<em>wrappedClass</em>' // cv::Vec2 *<em>wrappedClass</em>; // cv::Vec3 *<em>wrappedClass</em>; };

Por supuesto, el ejemplo anterior no funcionará porque cv::Vec espera que especifique el type y el size. Entonces, algo como esto: cv::Vec<int, 3> funcionaría y crearía un vector tridimensional.

Mi pregunta es cómo sobrecargar correctamente el constructor y definir el tipo _wrappedClass_.

¿Debo crear clases Vec2, Vec3, y así sucesivamente, que extiendan la clase actual Vec?

Cuando miré cómo los desarrolladores más experimentados abordaban el problema, encontré este ejemplo en opencv4nodejs. Parece más razonable:

  • 1 archivo cpp
  • archivo de encabezado base
  • archivos de encabezado adicionales para las variantes de clase

Tengo un ejemplo completo en GitHub aquí.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para la sobrecarga adecuada del constructor y para definir el tipo _wrappedClass_, se pueden utilizar plantillas para crear una clase genérica Vec. Luego, se pueden crear clases específicas Vec2, Vec3, etc. que heredan de la clase genérica Vec, especificando el tamaño y el tipo en los argumentos de la plantilla.

    Aquí hay un ejemplo de implementación:

    #include <napi.h>
    #include <opencv2 core/matx.hpp="">
    
    // Clase Vec genérica con argumentos de plantilla para el tamaño y el tipo
    template <int size,="" typename="" type="">
    class Vec : public Napi::ObjectWrap<><size, type="">> {
    public:
      static Napi::Object Init(Napi::Env env, Napi::Object exports) {
        // Definir la función constructora
        Napi::Function func = DefineClass(env, "Vec", {
          // Agregar sobrecarga del constructor que toma valores para cada elemento
          InstanceMethod("constructor", &Vec<size, type="">::Construct, napi_enumerable),
          // Agregar métodos getter y setter para cada elemento
          InstanceAccessor("elem0", &Vec<size, type="">::GetElem<0>, &Vec<size, type="">::SetElem<0>, napi_enumerable),
          InstanceAccessor("elem1", &Vec<size, type="">::GetElem<1>, &Vec<size, type="">::SetElem<1>, napi_enumerable),
          // Repetir para cada elemento hasta el tamaño Size
        });
    
        // Cachear la función constructora para su uso posterior
        constructor = Napi::Persistent(func);
        constructor.SuppressDestruct();
    
        // Agregar la clase a los exports
        exports.Set("Vec", func);
    
        return exports;
      }
    
      explicit Vec(const Napi::CallbackInfo& info) : Napi::ObjectWrap<><size, type="">>(info) {
        // Inicializar _wrappedClass_ con los argumentos del constructor
        for (int i = 0; i < Size; i++) {
          _wrappedClass_[i] = info[i].As<type>();
        }
      }
    
      // Definir métodos getter y setter para cada elemento
      template <int index="">
      Napi::Value GetElem(const Napi::CallbackInfo& info) {
        return Napi::Value::From(info.Env(), _wrappedClass_[Index]);
      }
    
      template <int index="">
      void SetElem(const Napi::CallbackInfo& info, const Napi::Value& value) {
        _wrappedClass_[Index] = value.As<type>();
      }
    
    private:
      static Napi::FunctionReference constructor;
    
      // Definir la clase envuelta como una matriz de tipo Type y tamaño Size
      Type _wrappedClass_[Size];
    };
    
    // Definir la referencia del constructor
    template <int size,="" typename="" type="">
    Napi::FunctionReference Vec<size, type="">::constructor;
    
    // Definir clases Vec especializadas para diferentes tamaños y tipos
    using Vec2f = Vec<2, float>;
    using Vec3f = Vec<3, float>;
    // Repetir para otros tipos y tamaños según sea necesario
    

    Con esta implementación, se puede crear una clase específica como Vec2f que herede de la clase genérica Vec<2, float>, por ejemplo. También se pueden agregar clases especializadas adicionales según sea necesario.

    Para utilizar esta implementación, se puede incluir el archivo de encabezado que define las clases Vec especializadas que se necesitan y llamar al método Init para crear la clase Vec y agregarla a los exports:

    “`cpp
    // Incluye las clases Vec especializadas
    #include “Vec2f.h”
    #include “Vec3i.h”

    Napi::Object Init(Napi::Env env, Napi::Object exports) {
    // Agregar las clases Vec especializadas a los exports
    Vec2f::Init(env, exports);
    Vec3i::Init(env, exports);
    // Repetir para otras clases Vec especializadas según sea necesario

    return exports;
    }
    “`</size,></size,></size,></size,></size,></size,></size,></size,></napi.h>

Comments are closed.