I'm currently working on a project where I need to simplfy an existing system. Wihtout going into the details the problem is that I get some function pointer (from type: void*) and I need to create a function from it (= create a function with signature). So my approach was to create the following variadic template function:
template <typename ReturnType, typename ... Params>
ReturnType(*GetFunction(void* func, Params ...)) (Params ...)
{
return reinterpret_cast<ReturnType(*) (Params ...)> (func);
}
Now I need a way to create the needed functions:
#define DECLARE_PARAMS(...) __VA_ARGS__
#define Define_Function(returnType, fname, Params) returnType Gen_##fname (DECLARE_PARAMS Params)\
{\
return FUNCTION_DIRECTCALL(returnType, fname, (DECLARE_PARAMS Params));\
}
and here is the Problem. (I think) the Params don't expand the way they should expand. But I don't know why?
I tested the FUNCTION_DIRECTCALL in the DEFINE_FUNCTION macro with hardcoded values (simple put the defintion into the directcall) and it worked so there shouldn't be an error but I'm open for improvements
#define FUNCTION_DIRECTCALL(returnType, functionName, ...) \
GetFunction<returnType>(functionName, DECLARE_PARAMS __VA_ARGS__) ( DECLARE_PARAMS __VA_ARGS__)
If I try to define a function with the macro
Define_Function(void, ThatFunction, (int a_, int b_)); // void ThatFunction(int a, int b);
I get the following error: "Severity Code Description Project File Line Suppression State Error (active) incomplete type is not allowed [...]\main.cpp 34"
So my question is, what am I doing wrong? Is the problem really related to the Params in the DEFINE_FUNCTION macro or did I miss something?
I worked with macros but I wouldn't call myself an expert in this area. But the way I understand it is that (DECLARE_PARAMS Params) should expand the params to:
int a_, int b_
and after the scan I would expect the following code:
void Gen_ThatFunction(int a_, int b_)
{
return GetFunction<void>(ThatFunction, a_, b_) (a_, b_);
}
Testing the Directcall macro: with the following code I tested the functionality of the directcall macro
Therefore I change the Define_Function macro:
#define Define_Function(returnType, fname, Params) returnType Gen_##fname (DECLARE_PARAMS Params) \
{\
int a = 2, b = 3;\
return FUNCTION_DIRECTCALL(void, ThatFunction, (a, b) );\
}
The definition of ThatFunction:
void ThatFunction(int a, int b)
{
std::cout << a << " * " << b << " = " << b * a << std::endl;
}
output: "2 * 3 = 6"
All code compiled in VC++ 2015
The only way I know how to do what you're asking is really clunky.
#define DEFINE_FUNCTION(RET, NAME, TYPES, NAMES, BOTH) RET Gen_##NAME BOTH { return reinterpret_cast<RET(*)TYPES>(NAME) NAMES; }
You use it like:
DEFINE_FUNCTION(void, ThatFunction, (int, int), (a_, b_), (int a_, int b_))
The return type and name of the void*
(or function) are the first two parameters. Next is the list of the argument types enclosed by parenthesis, the argument names enclosed as well, and lastly the enclosed types AND names. Like I said, clunky.
This would generate the function:
void Gen_ThatFunction (int a_, int b_) { return reinterpret_cast<void(*)(int, int)>(ThatFunction) (a_, b_); }
You can then call the function as you wish:
Gen_ThatFunction(2, 3); //prints "2 * 3 = 6"
Of course, keep in mind this is Microsoft specific. Here, comma separated items enclosed by parenthesis are a single macro parameter. On any other compiler, this wouldn't work (that I'm aware of).