-
Notifications
You must be signed in to change notification settings - Fork 470
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Template conversions to c++ types #681
Comments
It was pointed out in the N-API meeting this week that something similar was discussed in: #639. |
@bergkvist can you take a look and see if the module referenced in #639 meets what you were asking for. |
I ended up solving it like this:#include <string>
#include <type_traits>
#define CPP_VALUE(return_type, statement) \
template <typename specified_return_type> \
typename std::enable_if_t< \
std::is_same<specified_return_type, return_type>::value, \
specified_return_type> \
cpp_value(const Napi::Value value) { \
return statement; \
}
CPP_VALUE(std::string, value.As<Napi::String>().Utf8Value())
CPP_VALUE(std::u16string, value.As<Napi::String>().Utf16Value())
CPP_VALUE(int32_t, value.As<Napi::Number>().Int32Value())
CPP_VALUE(int64_t, value.As<Napi::Number>().Int64Value())
CPP_VALUE(uint32_t, value.As<Napi::Number>().Uint32Value())
CPP_VALUE(float, value.As<Napi::Number>().FloatValue())
CPP_VALUE(double, value.As<Napi::Number>().DoubleValue())
CPP_VALUE(uint32_t *, value.As<Napi::Uint32Array>().Data())
CPP_VALUE(uint16_t *, value.As<Napi::Uint16Array>().Data())
CPP_VALUE(uint8_t *, value.As<Napi::Uint8Array>().Data())
CPP_VALUE(int32_t *, value.As<Napi::Int32Array>().Data())
CPP_VALUE(int16_t *, value.As<Napi::Int16Array>().Data())
CPP_VALUE(int8_t *, value.As<Napi::Int8Array>().Data()) Which enables me to do:Napi::Number add(const Napi::CallbackInfo &info) {
auto x = cpp_value<double>(info[0]);
auto y = cpp_value<double>(info[1]);
return Napi::Number::New(info.Env(), x + y);
} This means it is now possible for me to write type-independent logic with templates for parsing arguments. It is also slightly less verbose. @mhdawson: #639 looks very interesting, and very much in line with what I'm trying to do here. There is one potential problem I'm seeing with it - which is to allow for accepting/destructuring a JavaScript Object as an argument. To extend my implementation above to allow for accepting a JavaScript object, it would be possible to do something like this: struct ObjectWrapper {
Napi::Object object;
ObjectWrapper(Napi::Object object) : object{object} {}
template <typename T>
T get(std::string key);
};
CPP_VALUE(ObjectWrapper, ObjectWrapper{value.As<Napi::Object>()})
template <typename T>
T ObjectWrapper::get(std::string key) {
return cpp_value(this->object.Get(key));
} Which allows for the following: // Can be called as add({ x: 3, y: 4 }) === 7 in Node.js
Napi::Number add(const Napi::CallbackInfo &info) {
const args = cpp_value<ObjectWrapper>(info[0]);
auto x = args.get<double>("x");
auto y = args.get<double>("y");
return Napi::Number::New(info.Env(), x + y);
} |
@bergkvist without having had time to dive into the details, is it possible to contribute a PR to #639 that would add your solution for accepting/destructuring a JavaScript Object as an argument. |
This issue is stale because it has been open many days with no activity. It will be closed soon unless the stale label is removed or a comment is made. |
Right now, conversion from JavaScript to C++-types are not very template-friendly.
Consider the following:
I propose something like the following (as an equivalent way of doing the same thing):
Advantages of this approach:
This would allow for useful utility templates/functions like:
Which would be equivalent to:
Alternatively, in case it becomes unclear when the
.As<T>()
conversion is implicit:The text was updated successfully, but these errors were encountered: