简体   繁体   English

如何创建一个 C++ 宏来定义使用调用另一个函数的参数列表的函数?

[英]How to create a C++ macro to define function that uses argument list that calls another function?

As bizarre as the title seems, what I want to do is fairly simple.尽管标题看起来很奇怪,但我想做的事情相当简单。 Look at these definitions:看看这些定义:

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));

I have a bunch of these definitions and I want to "turn them into a function".我有一堆这样的定义,我想“把它们变成一个函数”。 I have tried something like this:我试过这样的事情:

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

The issue is how to parse the function arguments and pass them to another function.问题是如何解析函数参数并将它们传递给另一个函数。 The SpoofCall function does look like this: 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) {

Is there even a way to do it?有没有办法做到这一点? I can define the function to accept a template and then just call the SpoofCall with these arguments, but I would like to have the function defined with the arguments so I can use them more easily and to integrate them with IntelliSense:我可以定义函数以接受模板,然后只使用这些参数调用 SpoofCall,但我希望使用参数定义函数,以便我可以更轻松地使用它们并将它们与 IntelliSense 集成:

截屏

EDIT: Changed typo in macro编辑:更改了宏中的错字

You can try something like:您可以尝试以下操作:

#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));
}

The symbol will be reference to function and not a function, but IntelliSense should accept that.该符号将引用函数而不是函数,但 IntelliSense 应该接受这一点。 The reference will be initialized at program startup.引用将在程序启动时初始化。 Allowing argument names is more problematic, but that should be possible using more function overload magic (see CppReference article for more information).允许参数名称更成问题,但应该可以使用更多的函数重载魔法(有关更多信息,请参阅CppReference 文章)。

EDIT: it was simpler indeed, as thing like float (int a, int b) is a valid type in C++:编辑:它确实更简单,因为像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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM