关于OBS Studio源码中含CALLBACK修饰的函数指针typedef声明的疑问
解读OBS中特殊的函数指针typedef声明
我明白你已经搞懂了常规的函数指针typedef写法,比如:
typedef void (*myType)(); // ^ ^ ^ // 返回类型 类型名 参数 myType x; void myFunc() { std::cout<<"Hello\n"; } x = &myFunc; x(); // 将输出"Hello"
但看到OBS源码里的这个声明就懵了:
//! 消息回调 typedef void (CALLBACK* PFN_VIDEO_CAPTURE_FILTER_NOTIFICATION_CALLBACK)(VIDEO_CAPTURE_FILTER_NOTIFICATION nMessage, void* pData, int nSize, void* pContext);
你疑惑的点在于为什么CALLBACK*和类型名PFN_VIDEO_CAPTURE_FILTER_NOTIFICATION_CALLBACK被放在同一个括号里,对吧?咱们来一步步拆解清楚:
首先得搞懂CALLBACK是什么——它是Windows平台预定义的宏,本质上是用来指定函数的调用约定的,通常对应__stdcall(不同编译环境可能有细微差异,但核心作用就是标记函数调用时的参数传递、栈清理规则)。
现在把这个声明拆成核心部分来看:
void:这是函数指针指向的函数的返回类型,和你熟悉的常规写法完全一致。(CALLBACK* PFN_VIDEO_CAPTURE_FILTER_NOTIFICATION_CALLBACK):这是整个声明的核心。你可以把它理解为:我们定义了一个名为PFN_VIDEO_CAPTURE_FILTER_NOTIFICATION_CALLBACK的类型,它是一个指向遵循CALLBACK调用约定的函数的指针。这里的CALLBACK必须和指针声明放在同一括号里,因为它是用来修饰指针指向的函数的调用规则的。- 后面的
(VIDEO_CAPTURE_FILTER_NOTIFICATION nMessage, void* pData, int nSize, void* pContext):就是这个函数指针指向的函数的参数列表,和常规函数指针写法没有区别。
如果把CALLBACK替换成它实际代表的__stdcall,这个声明就会变得和你熟悉的写法更贴近:
typedef void (__stdcall* PFN_VIDEO_CAPTURE_FILTER_NOTIFICATION_CALLBACK)(VIDEO_CAPTURE_FILTER_NOTIFICATION nMessage, void* pData, int nSize, void* pContext);
最后再梳理一下这个声明的解读顺序,帮你彻底搞明白:
- 看到最外层的
typedef,先明确这是在定义一个类型别名。 - 定位到括号里的
* PFN_VIDEO_CAPTURE_FILTER_NOTIFICATION_CALLBACK,确定这是一个函数指针类型,类型名就是PFN_VIDEO_CAPTURE_FILTER_NOTIFICATION_CALLBACK。 CALLBACK修饰这个函数指针,说明它指向的函数必须遵循CALLBACK指定的调用约定(这是Windows API里很常见的要求,用来保证函数调用的栈行为一致)。- 前面的
void是函数的返回类型,后面括号里的是函数的参数列表。
内容的提问来源于stack exchange,提问作者Alok
相关产品推荐
相关产品推荐

