pmed / v8pp

Bind C++ functions and classes into V8 JavaScript engine
http://pmed.github.io/v8pp/
Other
898 stars 120 forks source link

Question: ctor with enum as param #54

Closed zealoushacker closed 7 years ago

zealoushacker commented 7 years ago

I am writing a nodejs addon.

When I attempt to create an std::vector<field> fields; and perform something like _fields = v8pp::from_v8<std::vector<field>>(isolate, args[0], fields);, I get the dreaded Error: expected C++ wrapped object when args[0] contains [{"name":"name","type":"text"},{"name":"birth_date","type":"date"}] for example, vs [], which leads me to believe that conversions aren't being done correctly, due to the fact that the type being passed is a string, whereas the thing it actually wants is a numeric, representing the data_type from the enum.

@pmed do you have any suggestions on how this might be more appropriately/correctly implemented?

Here's are the relevant parts of my implementation:

void InitAll(Handle<Object> exports, Handle<Object> module) {
    //...
    v8pp::class_<field> field_js(isolate);
    field_js
        .ctor<const char *, data_type>()
        .set("name", v8pp::property(&field::name))
        .set("type", v8pp::property(&field::type));
    //...
}

and:

//...
class PUBLIC field {
private:

    struct _field_data_wrapper;
    _field_data_wrapper *_field_data;

public:

    field(const char *name, const data_type type);
//...
}

data_type is an enum:

enum data_type {
//...
}
zealoushacker commented 7 years ago

I think the problem with what I am trying to do is that when an array like [{"name":"name","type":"text"},{"name":"birth_date","type":"date"}] is passed, sure I am converting to an std::vector<field>, but then each member of the array is an std::map of sorts, rather than a field, because the field doesn't have a ctor for an std::map.

Thoughts on how to implement this "more correctly"?

zealoushacker commented 7 years ago

Attempting to do this, didn't yield better results:

void InitAll(Handle<Object> exports, Handle<Object> module) {
    //...
    v8pp::class_<field> field_js(isolate);
    field_js
       .ctor<const std::map<const char *, const char *>>() // **note the change here to an std::map** 
        .set("name", v8pp::property(&field::name))
        .set("type", v8pp::property(&field::type));
    //...
}

Of course, there was a new constructor on the field class:

field(const std::map<const char *, const char *> map);
zealoushacker commented 7 years ago

Perhaps this is the crucial hint to doing what I need to do here?

pmed commented 7 years ago

Maybe you don't need to wrap C++ field class with v8pp::class_ and v8pp::convert<field> specialization would be sufficient.

Here is a comment with details: https://github.com/pmed/v8pp/issues/17#issuecomment-138101271 and some here is some documentation: https://github.com/pmed/v8pp/blob/master/docs/convert.md#user-defined-types