简体   繁体   中英

Defining a function using a function typedef in C++

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 a macro which expands to the desired type
#define defLedClkFunc(name)   void (name)(uint16_t led)
  • Use the macro to define your typedef
typedef defLedClkFunc(tLedClkFunction);
  • Use the macro when declaring the function implementation
//********************************************************
//
// 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.

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