Skip to content

Instantly share code, notes, and snippets.

@xaxxon
Created January 15, 2016 04:38
Show Gist options
  • Save xaxxon/4d78a903d0327932d713 to your computer and use it in GitHub Desktop.
Save xaxxon/4d78a903d0327932d713 to your computer and use it in GitHub Desktop.
// Responsible for calling the actual method and populating the return type for non-void return type methods
template<typename METHOD_TYPE>
struct RunMethod {};
/**
* Specialization for methods that don't return void. Sets v8::FunctionCallbackInfo::GetReturnValue to value returned by the method
*/
template<typename RETURN_TYPE, typename CLASS_TYPE, typename ... PARAMETERS>
struct RunMethod<RETURN_TYPE(CLASS_TYPE::*)(PARAMETERS...)>{
typedef RETURN_TYPE(CLASS_TYPE::*METHOD_TYPE)(PARAMETERS...);
void operator()(CLASS_TYPE & object, METHOD_TYPE method, const v8::FunctionCallbackInfo<v8::Value> & info, PARAMETERS... parameters) {
RETURN_TYPE return_value = (object.*method)(parameters...);
auto casted_result = CastToJS<RETURN_TYPE>()(info.GetIsolate(), return_value);
info.GetReturnValue().Set(casted_result);
}
};
/**
* Specialization for methods that return void. No value set for v8::FunctionCallbackInfo::GetReturnValue
* The javascript call will return the javascript "undefined" value
*/
template<typename CLASS_TYPE, typename ... PARAMETERS>
struct RunMethod<void(CLASS_TYPE::*)(PARAMETERS...)> {
typedef void(CLASS_TYPE::*METHOD_TYPE)(PARAMETERS...);
void operator()(CLASS_TYPE & object, METHOD_TYPE method, const v8::FunctionCallbackInfo<v8::Value> &, PARAMETERS... parameters) {
(object.*method)(parameters...);
}
};
/**
* Class for turning a function parameter list into a parameter pack useful for actually calling the function
*/
template<int depth, typename T, typename U>
struct Caller {};
/**
* Specialization for when there are no parameters left to process, so it is time to actually
* call the function
*/
template<int depth, typename METHOD_TYPE, typename RET, typename CLASS_TYPE>
struct Caller<depth, METHOD_TYPE, RET(CLASS_TYPE::*)()> {
public:
// the final class in the call chain stores the actual method to be called
enum {DEPTH=depth, ARITY=0};
// This call method actually calls the method with the specified object and the
// parameter pack that was built up via the chain of calls between templated types
template<typename ... Ts>
void operator()(METHOD_TYPE method, CLASS_TYPE & object, const v8::FunctionCallbackInfo<v8::Value> & info, Ts... ts) {
RunMethod<METHOD_TYPE>()(object, method, info, ts...);
}
};
template<int depth, typename METHOD_TYPE, typename RET, typename CLASS_TYPE>
struct Caller<depth, METHOD_TYPE, RET(CLASS_TYPE::*)() const> {
public:
// the final class in the call chain stores the actual method to be called
enum {DEPTH=depth, ARITY=0};
// This call method actually calls the method with the specified object and the
// parameter pack that was built up via the chain of calls between templated types
template<typename ... Ts>
void operator()(METHOD_TYPE method, CLASS_TYPE & object, const v8::FunctionCallbackInfo<v8::Value> & info, Ts... ts) {
RunMethod<METHOD_TYPE>()(object, method, info, ts...);
}
};
/** END TEST CODE ****/
/**
* specialization that strips off the first remaining parameter off the method type, stores that and then
* inherits from another instance that either strips the next one off, or if none remaining, actually calls
* the method
* The method type is specified twice because the first is actually used by the final specialization to hold the
* method type while the second one has its input parameter list stripped off one at a time to determine when
* the inheritance chain ends
*/
template<int depth, typename METHOD_TYPE, typename CLASS_TYPE, typename RET, typename HEAD, typename...TAIL>
struct Caller<depth, METHOD_TYPE, RET(CLASS_TYPE::*)(HEAD,TAIL...)> : public Caller<depth+1, METHOD_TYPE, RET(CLASS_TYPE::*)(TAIL...)> {
public:
typedef Caller<depth+1, METHOD_TYPE, RET(CLASS_TYPE::*)(TAIL...)> super;
enum {DEPTH = depth, ARITY=super::ARITY + 1};
template<typename ... Ts>
void operator()(METHOD_TYPE method, CLASS_TYPE & object, const v8::FunctionCallbackInfo<v8::Value> & info, Ts... ts) {
CastToNative<HEAD> cast;
this->super::operator()(method, object, info, ts..., cast(info[depth]));
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment