4

我正在 Windows 中实现一项服务。VisualStudio 2012 具有以下函数 typedef:

typedef VOID WINAPI SERVICE_MAIN_FUNCTIONW (
    DWORD dwNumServicesArgs,
    LPWSTR *lpServiceArgVectors
);

还有一个函数指针typedef:

typedef VOID (WINAPI *LPSERVICE_MAIN_FUNCTIONW)(
    DWORD   dwNumServicesArgs,
    LPWSTR  *lpServiceArgVectors
);

如何使用 typedef 定义具有此函数签名的函数?

4

5 回答 5

7

引用当前的 C++ 标准 (C++11):

[dcl.fct]/10

函数类型的 typedef 可用于声明函数,但不得用于定义函数 (8.4)。[例子:

typedef void F();
F fv;             // OK: equivalent to void fv();
F fv { }          // ill-formed
void fv() { }     // OK: definition of fv

—结束示例]

也就是说,您可以使用 that 声明但不能定义函数typedef。您必须明确指定签名,请参阅 Alex Farber 的回答。


在某种程度上,您可以使用typedef来“定义”函数,但它涉及一些模板魔法。这是一个有趣的示例,表明您实际上可以使用它来定义函数。

// 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);
}
于 2013-05-07T05:22:25.680 回答
2

使用 C++11,您可以使用具有空捕获列表的 lambda 可转换为函数指针这一事实来声明和定义与一个表达式中的函数 typedef 匹配的函数,例如:

using my_function_t = void(*)(int,int);

my_function_t add_function = [](int x, int y) { return x + y; };
于 2017-02-27T13:10:27.693 回答
1

不能使用 . _ _ typedef它必须以常规方式定义。例如

void foo (type1 t1, type2 t2) // t1 and t2 are objects which can be ... 
{                             // ... visible only in conventional way
  ...
}

函数指针 typedef 可以声明函数指针,它可以分配函数的地址:

typedef void (*PF)(type1, type2);
PF pf = &foo;
于 2013-05-07T05:13:48.457 回答
1

您不需要(也不能)在函数定义中使用 typedef。要创建一个服务主函数,只需编写:

VOID WINAPI SvcMain( DWORD dwNumServicesArgs, LPWSTR *lpServiceArgVectors )
{
    // ...
}

LPSERVICE_MAIN_FUNCTIONWWindows 内部使用它来调用每个服务起点。通常,您需要函数指针typedef来调用,而不是定义函数。

于 2013-05-07T05:15:48.587 回答
0

这可以通过反转尝试的方法来实现。

  • 定义一个扩展为所需类型的宏
#define defLedClkFunc(name)   void (name)(uint16_t led)
  • 使用宏来定义你的 typedef
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,
                             };

现在您有了函数签名的单点定义,并且对签名的任何更改都会通过所有 typedef 和函数声明传播。

我发现这对于定义函数集(例如中断处理程序、消息处理程序)非常有用。

此外,如果有人决定它们都应该有一些任意的前缀和/或后缀,宏使得更改所有函数名称变得很简单。只需将标记粘贴用作宏定义的一部分,然后将所需的前缀/后缀粘贴到name.

确实需要记住为操作指向函数的指针而创建的数据类型,但即使这样也可以通过微不足道的额外宏魔术自动适应。

于 2021-05-01T22:27:37.460 回答