Как создать макрос C ++ для определения функции, которая использует список аргументов, который вызывает другую функцию? - PullRequest
1 голос
/ 27 марта 2020

Как ни странно, как кажется название, то, что я хочу сделать, довольно просто. Посмотрите на эти определения:

ImportFunc(void, il2cpp_init_utf16, (const Il2CppChar* domain_name));
ImportFunc(void, il2cpp_shutdown, ());
ImportFunc(void, il2cpp_set_config_dir, (const char* config_path));
ImportFunc(void, il2cpp_set_data_dir, (const char* data_path));
ImportFunc(void, il2cpp_set_commandline_arguments, (int argc, const char* const argv[], const char* basedir));
ImportFunc(void, il2cpp_set_commandline_arguments_utf16, (int argc, const Il2CppChar* const argv[], const char* basedir));
ImportFunc(void, il2cpp_set_config_utf16, (const Il2CppChar* executablePath));
ImportFunc(void, il2cpp_set_config, (const char* executablePath));

У меня есть куча этих определений, и я хочу «превратить их в функцию». Я пробовал что-то вроде этого:

#define ImportFunc(t, n, a) \
t n a \
{ \
void* pfunc = (void*)CallSystem(kernel32, GetProcAddress, Globals::GameAssembly, n); \
return SpoofCall<type>((void*)pfunc, args...); \
}

Проблема заключается в том, как проанализировать аргументы функции и передать их другой функции. Функция SpoofCall выглядит следующим образом:

template<typename Ret = void, typename First = void*, typename Second = void*, typename Third = void*, typename Fourth = void*, typename... Stack>
    __forceinline Ret SpoofCall(void* Func, First a1 = First{}, Second a2 = Second{}, Third a3 = Third{}, Fourth a4 = Fourth{}, Stack... args) {

Есть ли способ сделать это? Я могу определить функцию для принятия шаблона, а затем просто вызвать SpoofCall с этими аргументами, но я бы хотел, чтобы функция была определена с аргументами, чтобы мне было проще использовать их и интегрировать их с IntelliSense:

screenshot

РЕДАКТИРОВАТЬ: Изменена опечатка в макросе

1 Ответ

1 голос
/ 29 марта 2020

Вы можете попробовать что-то вроде:

#define ImportFunc(_type,_name,...) \
        _type (&x_##_name) (__VA_ARGS__) = *ImportT<_type,## __VA_ARGS__>(#_name)

// Convenience typedef, as spelling template function
// returning template pointer to function
// is *too* error-prone otherwise
template <typename Ret, typename ...Args>
using FuncT = Ret (Args...);

template <typename Ret, typename ...Args>
FuncT<Ret, Args...> *ImportT(char const *name) {
        std::printf("Name: %s\n", name);
        return (FuncT<Ret, Args...> *)dlsym(RTLD_DEFAULT, name); // GetProcAddress on windows
}       

ImportFunc(double, sin, double);
ImportFunc(double, sqrt, double);
ImportFunc(int, fn3, float);

int main() {
        printf("sin(1) = %.3f\n", x_sin(1.0f));
        printf("sqrt(2) = %.3f\n", x_sqrt(2.0f));
}

Символ будет ссылаться на функцию, а не на функцию, но IntelliSense должен принять это. Ссылка будет инициализирована при запуске программы. Разрешение имен аргументов более проблематично c, но это должно быть возможно при использовании большего количества магических перегрузок функций c (для получения дополнительной информации см. статью CppReference ).

РЕДАКТИРОВАТЬ: это действительно было проще , например, float (int a, int b) является допустимым типом в C ++:

#define ImportFunc(_type,_name,...) \
        _type (&x_##_name) (__VA_ARGS__) = *ImportT<_type (__VA_ARGS__)>(#_name)

template <typename Func>
Func *ImportT(char const *name) {
        std::printf("Name: %s\n", name);
        return (Func *)dlsym(RTLD_DEFAULT, name); // GetProcAddress on windows
}       

ImportFunc(double, sin, double t);
ImportFunc(double, sqrt, double x);
ImportFunc(int, fn3, float a, char const * b);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...