I am implementing a service in Windows. VisualStudio 2012 has the following function typedef:
typedef VOID WINAPI SERVICE_MAIN_FUNCTIONW (
DWORD dwNumServicesArgs,
LPWSTR *lpServiceArgVectors
);
There is also a function pointer typedef:
typedef VOID (WINAPI *LPSERVICE_MAIN_FUNCTIONW)(
DWORD dwNumServicesArgs,
LPWSTR *lpServiceArgVectors
);
How do I define a function with this function signature, using the typedef?
Quoting the current C++ Standard (C++11):
[dcl.fct]/10
A typedef of function type may be used to declare a function but shall not be used to define a function (8.4). [Example:
typedef void F(); F fv; // OK: equivalent to void fv(); F fv { } // ill-formed void fv() { } // OK: definition of fv
—end example ]
That is, you can declare but not define the function using that typedef
. You have to specify the signature explicitly, see Alex Farber's answer.
To some extent, you can use the typedef
to "define" the function, but it involves some template magic. It's a just-for-fun example to show that you can actually use it to define a function.
// extra definitions for SSCCE
typedef unsigned int DWORD;
typedef wchar_t* LPWSTR;
#define VOID void
#define WINAPI
// function ptr
typedef VOID (WINAPI *LPSERVICE_MAIN_FUNCTIONW)(
DWORD dwNumServicesArgs,
LPWSTR *lpServiceArgVectors
);
// function typedef
typedef VOID WINAPI SERVICE_MAIN_FUNCTIONW (
DWORD dwNumServicesArgs,
LPWSTR *lpServiceArgVectors
);
template < typename... TT >
struct disassemble_funcptr
{};
template < typename Ret, typename... Args >
struct disassemble_funcptr < Ret(Args...) >
{
typedef Ret return_type;
static Ret Func(Args...)
{
/* your code here */
}
};
// using the typedef SERVICE_MAIN_FUNCTIONW to define the function
LPSERVICE_MAIN_FUNCTIONW my_func_ptr =
& disassemble_funcptr < SERVICE_MAIN_FUNCTIONW > :: Func;
int main()
{
LPWSTR str = nullptr;
my_func_ptr(42, &str);
}
A function cannot be defined
(or declared)
using a typedef
. It has to be defined in the conventional way. eg
void foo (type1 t1, type2 t2) // t1 and t2 are objects which can be ...
{ // ... visible only in conventional way
...
}
Function pointer typedef can declare function pointer, which can be assigned with the function's address:
typedef void (*PF)(type1, type2);
PF pf = &foo;
You don't need (and cannot) use typedef in a function definition. To make a service main function, just write:
VOID WINAPI SvcMain( DWORD dwNumServicesArgs, LPWSTR *lpServiceArgVectors )
{
// ...
}
LPSERVICE_MAIN_FUNCTIONW
is used internally by Windows to call every service start point. Generally, you need function pointer typedef
to call, and not to define a function.
With C++11, you can use the the fact that lambdas with empty capture lists are convertible to function pointers to declare and define a function that matches a function typedef in one expression, eg:
using my_function_t = void(*)(int,int);
my_function_t add_function = [](int x, int y) { return x + y; };
This can be accomplished by inverting the attempted approach.
#define defLedClkFunc(name) void (name)(uint16_t led)
typedef defLedClkFunc(tLedClkFunction);
//********************************************************
//
// Declaration of first function
//
defLedClkFunc(ledClkEnable)
{
// Body of first function
} // ledClkEnable()
//********************************************************
//
// Declaration of second function
//
defLedClkFunc(ledClkDisable)
{
// Body of second function
} // ledClkDisable()
//
// Create an array of pointers to the functions
//
tLedClkFunction *myFuncs[] = {
ledClkEnable,
ledClkDisable,
};
Now you have a single-point definition of the function signature, and any changes to the signature propagate through all of the typedefs and function declarations.
I find this incredibly useful for defining sets of functions (eg interrupt handlers, message handlers).
In addition, the macro makes it trivial to change * all function names if someone decides they should all have some arbitrary prefix and/or suffix. Just use token pasting as part of the macro definition and paste the desired prefix/suffix around name
.
You do need to remember the data type created in order to manipulate pointers to the functions, but even that could be auto-adapted with a trivial amount of additional macro-magery.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.