使用可变包类型扩展的 C++ 函数调用包装器
C++ function caller wrapper using variadic pack types expansion
我绑定到一些 API 并且我绑定到一些函数签名,如下所示:
static bool WrapperFunction(JSContext *cx, unsigned argc, JS::Value *vp)
我尝试包装对象和函数以在 SpiderMonkey 下的 javascript 中使用。
要集成某些 C API,必须实现对象数据的包装器和某些对象的包装器方法。
我的解决方案将我引向包装器的以下逻辑,以便能够调用带有多个参数的方法,但我不知道如何实现它:
template<typename jsType, typename jsReturnType, typename MethodType, MethodType Method, typename... jsParamType>
static bool VAMethodRet(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = CallArgsFromVp(argc, vp);
jsReturnType::PrivateType result = jsReturnType::PrivateTypeDefaultValue();
我的问题从这里开始:
Expand ...jsParamType
... pack 为每个 jsParamType 调用一个方法,以便创建一个包装器 class 对象实例来匹配相应的参数准备调用 C API 函数的参数。
换句话说,jsParamType
告诉它包装的类型,以便它可以为要传递给 C API 函数的每个参数提取 C 类型对象。
第一个jsParamType
对应args[0]
,第二个jsParamType
对应args[1]
,以此类推,最后一个jsParamType
对应args[argc]
.
args 中的元素可能少于 sizeof...jsParamType
,在这种情况下,应使用默认值初始化基本 C 对象。
参数或对象包装器的元信息已经通过静态方法实现(例如jsParamType::jsType::PrivateTypeDefaultValue()
)。
最终,扩展包应该是异构对象的数组或向量。
匹配函数应该基于 jsParamType 进行模板化,而且还获取扩展可变参数包的索引和 args 局部变量以获得要解析的正确对象 - 这是我的第一个问题:
如何将索引传递给方法?
我试图从 here 中获得灵感,但我无法做到。
2.. 在此之后,我计划采用与 here 类似的技术,以便使用正确的参数调用 C API 函数 - 这可能吗?
- 最后,基于
jsParamType
的一个静态函数,称为IsOut()
,输出值将更新args
局部变量的内容,但这应该再次进行使用类似于第一步的新扩展,使用 jsParamType
元素中存在的类型信息放回一些值。
最后要做的是设置 return 值,这很简单。
感谢AndyG的帮助和耐心,我达到了我的目标。这是一个代码示例,请注意未提供实际包装器,因为它们因情况而异。所以,它们是通过简单地传递参数来模拟的。
#include <iostream>
#include <functional>
#include <tuple>
#include <type_traits>
#include <vector>
using namespace std;
#include <functional>
#include <tuple>
#include <type_traits>
using namespace std;
template<typename T, typename U, std::enable_if_t<std::is_same<T, U>::value, int> = 0>
T convert_type(U _in)
{
//return const_cast<U>(_in);
return _in;
}
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
T convert_type(U _in)
{
//return const_cast<U>(_in);
return _in;
}
// these conversion functions only can convert type to pointer to type, else return reference to type, so they're a bit limited
// pointer to pointer, or
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
T& convert_type(U& _in)
{
return _in;
}
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<U>>::value, int> = 0>
T& convert_type(U& _in)
{
return _in;
}
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<std::add_const_t<U>>>::value, int> = 0>
T& convert_type(U& _in)
{
return _in;
}
// for conversion to pointer
//T&* to T*
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<U>>::value, int> = 0>
T convert_type(U& _in)
{
return std::addressof(_in);
}
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
T convert_type(U& _in)
{
return std::addressof(_in);
}
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<std::add_const_t<U>>>::value, int> = 0>
T convert_type(U& _in)
{
return std::addressof(_in);
}
template<typename T>
struct function_traits;
template<typename R, typename ...Args>
struct function_traits<std::function<R(Args...)>>
{
static const size_t nargs = sizeof...(Args);
typedef R result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
static const bool isGlobalOrStaticContainer = true;
static const bool isClassContainer = false;
static const bool isPointerContainer = false;
static const bool isConstInClassContainer = false;
static const bool returnsVoid = std::is_same<R, void>::value;
};
template<typename C, typename R, typename ...Args>
struct function_traits<std::function<R(*C::*)(Args...)>>
{
static const size_t nargs = sizeof...(Args);
typedef R result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
static const bool isGlobalOrStaticContainer = false;
static const bool isClassContainer = false;
static const bool isPointerContainer = true;
static const bool isConstInClassContainer = false;
static const bool returnsVoid = std::is_same<R, void>::value;
};
template<typename C, typename R, typename ...Args>
struct function_traits<std::function<R(C::*)(Args...)>>
{
static const size_t nargs = sizeof...(Args);
typedef R result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
static const bool isGlobalOrStaticContainer = false;
static const bool isClassContainer = true;
static const bool isPointerContainer = false;
static const bool isConstInClassContainer = false;
static const bool returnsVoid = std::is_same<R, void>::value;
};
template<typename C, typename R, typename ...Args>
struct function_traits<std::function<R(C::*)(Args...) const>>
{
static const size_t nargs = sizeof...(Args);
typedef R result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
static const bool isGlobalOrStaticContainer = false;
static const bool isClassContainer = true;
static const bool isPointerContainer = false;
static const bool isConstInClassContainer = true;
static const bool returnsVoid = std::is_same<R, void>::value;
};
template<typename ParamType> class Param
{
public:
typedef ParamType Type;
static const bool isOut = false;
};
template<typename ParamType> class ParamOut : public Param<ParamType>
{
public:
static const bool isOut = true;
};
template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename ParamType, size_t paramIndex, typename... ParamTypes>
static bool UnwrapParameter(unsigned argc, std::vector<void*>& args, typename ParamType::Type &ppt)
{
if (argc > paramIndex)
{
ppt = *((std::add_pointer_t<typename ParamType::Type>(args[paramIndex])));
}
return true;
}
template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType, size_t... paramIndex>
static bool UnwrapParameters(unsigned argc, std::vector<void*>& args, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
{
bool r[] = { true, UnwrapParameter<Type, ReturnType, MethodType, Method, ParamType, paramIndex, ParamType...>(argc, args, std::get<paramIndex>(params))... };
bool res = true;
for (size_t i = 0; i < sizeof...(ParamType) + 1 && res == true; i++)
res &= r[i];
return res;
}
template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType>
static bool UnwrapParameters(unsigned argc, std::vector<void*>& args, std::tuple<typename ParamType::Type...>& params)
{
return UnwrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params, std::make_index_sequence<sizeof...(ParamType)>{});
}
template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename ParamType, size_t paramIndex, typename... ParamTypes>
static bool WrapParameter(unsigned argc, std::vector<void*>& args, typename ParamType::Type &ppt)
{
if (ParamType::isOut && (argc > paramIndex))
{
// Wrap them back - nothing to do here, in this example
}
return true;
}
template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType, size_t... paramIndex>
static bool WrapParameters(unsigned argc, std::vector<void*>& args, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
{
bool r[] = { true, WrapParameter<Type, ReturnType, MethodType, Method, ParamType, paramIndex, ParamType...>(argc, args, std::get<paramIndex>(params))... };
bool res = true;
for (size_t i = 0; i < sizeof...(ParamType)+1 && res == true; i++)
res &= r[i];
return res;
}
template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType>
static bool WrapParameters(unsigned argc, std::vector<void*>& args, std::tuple<typename ParamType::Type...>& params)
{
return WrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params, std::make_index_sequence<sizeof...(ParamType)>{});
}
template<typename Type, typename ReturnType, typename MethodType,
typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::isPointerContainer, MethodType>::type Method,
typename... ParamType, size_t... paramIndex>
static ReturnType CallMethodRet(bool& success, Type* obj, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
{
if (!(obj && (obj->*Method)))
success = false;
return (obj->*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
}
template<typename Type, typename ReturnType, typename MethodType,
typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::isGlobalOrStaticContainer, MethodType>::type Method,
typename... ParamType, size_t... paramIndex>
static ReturnType CallMethodRet(bool& success, Type* obj, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
{
if (!(*Method))
success = false;
return (*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
}
template<typename Type, typename ReturnType, typename MethodType,
typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::isClassContainer, MethodType>::type Method,
typename... ParamType, size_t... paramIndex>
static ReturnType CallMethodRet(bool& success, Type* obj, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
{
if (!(obj && (Method)))
success = false;
return (obj->*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
}
template <typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType>
static ReturnType CallMethodRet(bool& success, Type* obj, std::tuple<typename ParamType::Type...>& params)
{
return CallMethodRet<Type, ReturnType, MethodType, Method, ParamType...>(success, obj, params, std::make_index_sequence<sizeof...(ParamType)>{});
}
template<typename Type, typename ReturnType, typename MethodType,
typename std::enable_if<!function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::returnsVoid, MethodType>::type Method,
typename... ParamType>
static bool ExecuteMethod(Type* obj, unsigned argc, std::vector<void*>& args, ReturnType& result)
{
try
{
const unsigned numArgs = sizeof...(ParamType);
std::tuple<typename ParamType::Type...> params = std::make_tuple(typename ParamType::Type()...);
if (!UnwrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params))
return false;
bool success = true;
result = CallMethodRet<Type, ReturnType, MethodType, Method, ParamType...>(success, obj, params);
if (!success)
return false; // Throw method not found here
if (!WrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params))
return false;
}
catch (...)
{
// whatever...
}
return true;
}
template<typename Type, typename ReturnType, typename MethodType,
typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::returnsVoid, MethodType>::type Method,
typename... ParamType>
static bool ExecuteMethod(Type* obj, unsigned argc, std::vector<void*>& args)
{
try
{
const unsigned numArgs = sizeof...(ParamType);
std::tuple<typename ParamType::Type...> params = std::make_tuple(typename ParamType::Type()...);
if (!UnwrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params))
return false;
bool success = true;
CallMethodRet<Type, ReturnType, MethodType, Method, ParamType...>(success, obj, params);
if (!success)
return false; // Throw method not found here
if (!WrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params))
return false;
}
catch (...)
{
// whatever...
}
return true;
}
class O
{
public:
void func(int a, string b, bool& c, const char* d)
{
std::cout << "Successfully called func with in values " << a << "," << b << "," << c << " and " << d << std::endl;
c = true;
std::cout << "Successfully called func with out values " << a << "," << b << "," << c << " and " << d << std::endl;
}
int func_i(int a, string b, bool& c, const char* d)
{
std::cout << "Successfully called func with in values " << a << "," << b << "," << c << " and " << d << std::endl;
c = false;
std::cout << "Successfully called func with out values " << a << "," << b << "," << c << " and " << d << std::endl;
return 1;
}
};
int main() {
int a = 1;
string b = "string";
bool c = false;
const char* d = "char*";
std::vector<void*> v {(void*)&a, (void*)&b, (void*)&c, (void*)&d};
std::cout << std::endl;
O o;
std::cout << ExecuteMethod<O, void, void(O::*)(int, string, bool&, const char*), &O::func, Param<int>, Param<string>, ParamOut<bool>, Param<const char*>>(&o, v.size(), v);
std::cout << std::endl << std::endl;
int result = 0;
std::cout << ExecuteMethod<O, int, int(O::*)(int, string, bool&, const char*), &O::func_i, Param<int>, Param<string>, ParamOut<bool>, Param<const char*>>(&o, v.size(), v, result) << std::endl;
std::cout << result << std::endl;
return 0;
}
我绑定到一些 API 并且我绑定到一些函数签名,如下所示:
static bool WrapperFunction(JSContext *cx, unsigned argc, JS::Value *vp)
我尝试包装对象和函数以在 SpiderMonkey 下的 javascript 中使用。
要集成某些 C API,必须实现对象数据的包装器和某些对象的包装器方法。
我的解决方案将我引向包装器的以下逻辑,以便能够调用带有多个参数的方法,但我不知道如何实现它:
template<typename jsType, typename jsReturnType, typename MethodType, MethodType Method, typename... jsParamType>
static bool VAMethodRet(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = CallArgsFromVp(argc, vp);
jsReturnType::PrivateType result = jsReturnType::PrivateTypeDefaultValue();
我的问题从这里开始:
Expand ...
jsParamType
... pack 为每个 jsParamType 调用一个方法,以便创建一个包装器 class 对象实例来匹配相应的参数准备调用 C API 函数的参数。换句话说,
jsParamType
告诉它包装的类型,以便它可以为要传递给 C API 函数的每个参数提取 C 类型对象。第一个
jsParamType
对应args[0]
,第二个jsParamType
对应args[1]
,以此类推,最后一个jsParamType
对应args[argc]
.args 中的元素可能少于
sizeof...jsParamType
,在这种情况下,应使用默认值初始化基本 C 对象。参数或对象包装器的元信息已经通过静态方法实现(例如
jsParamType::jsType::PrivateTypeDefaultValue()
)。最终,扩展包应该是异构对象的数组或向量。
匹配函数应该基于 jsParamType 进行模板化,而且还获取扩展可变参数包的索引和 args 局部变量以获得要解析的正确对象 - 这是我的第一个问题:
如何将索引传递给方法?
我试图从 here 中获得灵感,但我无法做到。
2.. 在此之后,我计划采用与 here 类似的技术,以便使用正确的参数调用 C API 函数 - 这可能吗?
- 最后,基于
jsParamType
的一个静态函数,称为IsOut()
,输出值将更新args
局部变量的内容,但这应该再次进行使用类似于第一步的新扩展,使用jsParamType
元素中存在的类型信息放回一些值。
最后要做的是设置 return 值,这很简单。
感谢AndyG的帮助和耐心,我达到了我的目标。这是一个代码示例,请注意未提供实际包装器,因为它们因情况而异。所以,它们是通过简单地传递参数来模拟的。
#include <iostream>
#include <functional>
#include <tuple>
#include <type_traits>
#include <vector>
using namespace std;
#include <functional>
#include <tuple>
#include <type_traits>
using namespace std;
template<typename T, typename U, std::enable_if_t<std::is_same<T, U>::value, int> = 0>
T convert_type(U _in)
{
//return const_cast<U>(_in);
return _in;
}
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
T convert_type(U _in)
{
//return const_cast<U>(_in);
return _in;
}
// these conversion functions only can convert type to pointer to type, else return reference to type, so they're a bit limited
// pointer to pointer, or
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
T& convert_type(U& _in)
{
return _in;
}
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<U>>::value, int> = 0>
T& convert_type(U& _in)
{
return _in;
}
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<std::add_const_t<U>>>::value, int> = 0>
T& convert_type(U& _in)
{
return _in;
}
// for conversion to pointer
//T&* to T*
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<U>>::value, int> = 0>
T convert_type(U& _in)
{
return std::addressof(_in);
}
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
T convert_type(U& _in)
{
return std::addressof(_in);
}
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<std::add_const_t<U>>>::value, int> = 0>
T convert_type(U& _in)
{
return std::addressof(_in);
}
template<typename T>
struct function_traits;
template<typename R, typename ...Args>
struct function_traits<std::function<R(Args...)>>
{
static const size_t nargs = sizeof...(Args);
typedef R result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
static const bool isGlobalOrStaticContainer = true;
static const bool isClassContainer = false;
static const bool isPointerContainer = false;
static const bool isConstInClassContainer = false;
static const bool returnsVoid = std::is_same<R, void>::value;
};
template<typename C, typename R, typename ...Args>
struct function_traits<std::function<R(*C::*)(Args...)>>
{
static const size_t nargs = sizeof...(Args);
typedef R result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
static const bool isGlobalOrStaticContainer = false;
static const bool isClassContainer = false;
static const bool isPointerContainer = true;
static const bool isConstInClassContainer = false;
static const bool returnsVoid = std::is_same<R, void>::value;
};
template<typename C, typename R, typename ...Args>
struct function_traits<std::function<R(C::*)(Args...)>>
{
static const size_t nargs = sizeof...(Args);
typedef R result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
static const bool isGlobalOrStaticContainer = false;
static const bool isClassContainer = true;
static const bool isPointerContainer = false;
static const bool isConstInClassContainer = false;
static const bool returnsVoid = std::is_same<R, void>::value;
};
template<typename C, typename R, typename ...Args>
struct function_traits<std::function<R(C::*)(Args...) const>>
{
static const size_t nargs = sizeof...(Args);
typedef R result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
static const bool isGlobalOrStaticContainer = false;
static const bool isClassContainer = true;
static const bool isPointerContainer = false;
static const bool isConstInClassContainer = true;
static const bool returnsVoid = std::is_same<R, void>::value;
};
template<typename ParamType> class Param
{
public:
typedef ParamType Type;
static const bool isOut = false;
};
template<typename ParamType> class ParamOut : public Param<ParamType>
{
public:
static const bool isOut = true;
};
template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename ParamType, size_t paramIndex, typename... ParamTypes>
static bool UnwrapParameter(unsigned argc, std::vector<void*>& args, typename ParamType::Type &ppt)
{
if (argc > paramIndex)
{
ppt = *((std::add_pointer_t<typename ParamType::Type>(args[paramIndex])));
}
return true;
}
template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType, size_t... paramIndex>
static bool UnwrapParameters(unsigned argc, std::vector<void*>& args, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
{
bool r[] = { true, UnwrapParameter<Type, ReturnType, MethodType, Method, ParamType, paramIndex, ParamType...>(argc, args, std::get<paramIndex>(params))... };
bool res = true;
for (size_t i = 0; i < sizeof...(ParamType) + 1 && res == true; i++)
res &= r[i];
return res;
}
template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType>
static bool UnwrapParameters(unsigned argc, std::vector<void*>& args, std::tuple<typename ParamType::Type...>& params)
{
return UnwrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params, std::make_index_sequence<sizeof...(ParamType)>{});
}
template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename ParamType, size_t paramIndex, typename... ParamTypes>
static bool WrapParameter(unsigned argc, std::vector<void*>& args, typename ParamType::Type &ppt)
{
if (ParamType::isOut && (argc > paramIndex))
{
// Wrap them back - nothing to do here, in this example
}
return true;
}
template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType, size_t... paramIndex>
static bool WrapParameters(unsigned argc, std::vector<void*>& args, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
{
bool r[] = { true, WrapParameter<Type, ReturnType, MethodType, Method, ParamType, paramIndex, ParamType...>(argc, args, std::get<paramIndex>(params))... };
bool res = true;
for (size_t i = 0; i < sizeof...(ParamType)+1 && res == true; i++)
res &= r[i];
return res;
}
template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType>
static bool WrapParameters(unsigned argc, std::vector<void*>& args, std::tuple<typename ParamType::Type...>& params)
{
return WrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params, std::make_index_sequence<sizeof...(ParamType)>{});
}
template<typename Type, typename ReturnType, typename MethodType,
typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::isPointerContainer, MethodType>::type Method,
typename... ParamType, size_t... paramIndex>
static ReturnType CallMethodRet(bool& success, Type* obj, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
{
if (!(obj && (obj->*Method)))
success = false;
return (obj->*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
}
template<typename Type, typename ReturnType, typename MethodType,
typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::isGlobalOrStaticContainer, MethodType>::type Method,
typename... ParamType, size_t... paramIndex>
static ReturnType CallMethodRet(bool& success, Type* obj, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
{
if (!(*Method))
success = false;
return (*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
}
template<typename Type, typename ReturnType, typename MethodType,
typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::isClassContainer, MethodType>::type Method,
typename... ParamType, size_t... paramIndex>
static ReturnType CallMethodRet(bool& success, Type* obj, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
{
if (!(obj && (Method)))
success = false;
return (obj->*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
}
template <typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType>
static ReturnType CallMethodRet(bool& success, Type* obj, std::tuple<typename ParamType::Type...>& params)
{
return CallMethodRet<Type, ReturnType, MethodType, Method, ParamType...>(success, obj, params, std::make_index_sequence<sizeof...(ParamType)>{});
}
template<typename Type, typename ReturnType, typename MethodType,
typename std::enable_if<!function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::returnsVoid, MethodType>::type Method,
typename... ParamType>
static bool ExecuteMethod(Type* obj, unsigned argc, std::vector<void*>& args, ReturnType& result)
{
try
{
const unsigned numArgs = sizeof...(ParamType);
std::tuple<typename ParamType::Type...> params = std::make_tuple(typename ParamType::Type()...);
if (!UnwrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params))
return false;
bool success = true;
result = CallMethodRet<Type, ReturnType, MethodType, Method, ParamType...>(success, obj, params);
if (!success)
return false; // Throw method not found here
if (!WrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params))
return false;
}
catch (...)
{
// whatever...
}
return true;
}
template<typename Type, typename ReturnType, typename MethodType,
typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::returnsVoid, MethodType>::type Method,
typename... ParamType>
static bool ExecuteMethod(Type* obj, unsigned argc, std::vector<void*>& args)
{
try
{
const unsigned numArgs = sizeof...(ParamType);
std::tuple<typename ParamType::Type...> params = std::make_tuple(typename ParamType::Type()...);
if (!UnwrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params))
return false;
bool success = true;
CallMethodRet<Type, ReturnType, MethodType, Method, ParamType...>(success, obj, params);
if (!success)
return false; // Throw method not found here
if (!WrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params))
return false;
}
catch (...)
{
// whatever...
}
return true;
}
class O
{
public:
void func(int a, string b, bool& c, const char* d)
{
std::cout << "Successfully called func with in values " << a << "," << b << "," << c << " and " << d << std::endl;
c = true;
std::cout << "Successfully called func with out values " << a << "," << b << "," << c << " and " << d << std::endl;
}
int func_i(int a, string b, bool& c, const char* d)
{
std::cout << "Successfully called func with in values " << a << "," << b << "," << c << " and " << d << std::endl;
c = false;
std::cout << "Successfully called func with out values " << a << "," << b << "," << c << " and " << d << std::endl;
return 1;
}
};
int main() {
int a = 1;
string b = "string";
bool c = false;
const char* d = "char*";
std::vector<void*> v {(void*)&a, (void*)&b, (void*)&c, (void*)&d};
std::cout << std::endl;
O o;
std::cout << ExecuteMethod<O, void, void(O::*)(int, string, bool&, const char*), &O::func, Param<int>, Param<string>, ParamOut<bool>, Param<const char*>>(&o, v.size(), v);
std::cout << std::endl << std::endl;
int result = 0;
std::cout << ExecuteMethod<O, int, int(O::*)(int, string, bool&, const char*), &O::func_i, Param<int>, Param<string>, ParamOut<bool>, Param<const char*>>(&o, v.size(), v, result) << std::endl;
std::cout << result << std::endl;
return 0;
}