Я дополняю скриптовый язык белки, и мне нужно, чтобы человек легко регистрировал в языке свою собственную обычную функцию. Чтобы язык мог его вызывать, его необходимо обобщить до SQFUNCTION (typedef SqInteger (*SQFUNCTION)(HSQUIRRELVM)).
Я создал шаблон, который получает информацию об этой функции и принимает аргументы, но мне нужно как-то передать туда указатель на функцию, которую написал человек. если я сделаю второй параметр шаблона, то компилятор не сможет преобразовать этот шаблон в SQFUNCTION. Я понятия не имею, как это реализовать.
template
T GetArg(HSQUIRRELVM v, SQInteger idx);
template
inline int GetArg(HSQUIRRELVM v, SQInteger idx) {
SQInteger val;
if (SQ_FAILED(sq_getinteger(v, idx, &val))) {
throw sq_throwerror(v, "Failed to get integer");
}
return static_cast(val);
}
template
Tuple GetArgsTuple(HSQUIRRELVM v, std::index_sequence) {
return std::make_tuple(GetArg(v, I + 2)...);
}
template
void PushReturnValue(HSQUIRRELVM v, ReturnType value);
template
inline void PushReturnValue(HSQUIRRELVM v, int value) {
sq_pushinteger(v, static_cast(value));
}
template
struct function_traits;
template
struct function_traits {
using return_type = Ret;
using argument_types = std::tuple;
static constexpr std::size_t arg_count = sizeof...(Args);
};
template
auto CallFunc(Callable&& func, Tuple&& t, std::index_sequence) {
return func(std::get(std::forward(t))...);
}
template
SQInteger SqFuncWrapper(HSQUIRRELVM v) {
using traits = function_traits;
using ArgTuple = typename traits::argument_types;
using RetType = typename traits::return_type;
constexpr std::size_t arg_count = traits::arg_count;
ArgTuple args = GetArgsTuple(v, std::make_index_sequence{});
try {
if (std::is_same_v) {
CallFunc(..., args, std::make_index_sequence{});
}
else {
RetType ret = CallFunc(..., args, std::make_index_sequence{});
PushReturnValue(v, ret);
}
}
catch (const std::exception &e)
{
return sq_throwerror(v, e.what());
}
return 1;
}
Подробнее здесь: https://stackoverflow.com/questions/789 ... ithout-cha