大家都知道,在C语音中指针的地位很重要,各种指针,功能很强大!但是用不好,指针也比较容易出问题。 这里介绍的是函数指针的一种应用方法,即使用函数指针来实现消息命令的注册与回调处理。
测试的处理函数,这里为了测试,都是空函数:
#include <stdio.h>
#include "test_msg_proc.h"
void proc_msg_reg(int cmd, const void *pData, int len)
{
printf("in proc_msg_reg , cmd: %d, data: %s, data len: %d\n", cmd, (const char *)pData, len);
//处理数据
}
void proc_msg_login(int cmd, const void *pData, int len)
{
printf("in proc_msg_login, cmd: %d, data: %s, data len: %d\n", cmd, (const char *)pData, len);
//处理数据
}
void proc_msg_test(int cmd, const void *pData, int len)
{
printf("in proc_msg_test , cmd: %d, data: %s, data len: %d\n", cmd, (const char *)pData, len);
//处理数据
}
函数指针定义:
//函数指针
typedef void (*pfunc)(int , const void *, int );
消息处理节点信息结构体:
//消息处理节点信息结构体
typedef struct MsgProcNodeInfo
{
int cmd; //消息名字
char name[64]; //用于存储消息名字,方便调试
pfunc func; //处理回调函数
}MsgProcNodeInfoSt;
接下来是一个消息信息结构体的数组定义,也就是关键部分,消息命令的注册表:
//消息处理注册表,注册命令字与其对应的处理函数
static MsgProcNodeInfoSt msgMap[]=
{
{0, "regCmd", proc_msg_reg},
{1, "loginCmd", proc_msg_login},
{2, "testCmd", proc_msg_test},
};
主处理函数,用于根据命令字在注册表里查找对应的处理函数,然后回调处理。这里面有个小技巧,如果命令字与数组索引正好是一致的,那可以直接拿命令字作为数组的下表去索引对应的节点调用其函数指针即可。
//处理函数
void proc_msg(int cmd, const void *pData, int len)
{
#if 1
//处理
int i = 0;
for ( i = 0; i < sizeof(msgMap)/sizeof(MsgProcNodeInfoSt); i++ )
{
if ( msgMap[i].cmd != cmd )
continue;
if ( msgMap[i].func == NULL )
continue;
msgMap[i].func(cmd, pData, len);
}
#else
//如果命令字正好与数组索引相同,也可以这样取巧,直接拿命令字作为索引用
if ( cmd >= sizeof(msgMap)/sizeof(MsgProcNodeInfoSt) ) //越界判断
return;
msgMap[cmd].func(cmd, pData, len);
#endif
}
主函数:
#include <stdio.h>
#include "test_msg_proc.h"
int main(int argc, char **argv)
{
proc_msg(0, "注册", sizeof("注册"));
proc_msg(1, "登录", sizeof("登录"));
proc_msg(2, "测试", sizeof("测试"));
return 0;
}
编译:
[fens@fens app/test_func_point]$make
gcc -Wall -I. -c main.c -o main.o
gcc -Wall -I. -c test_msg_proc.c -o test_msg_proc.o
gcc ./main.o ./test_msg_proc.o -o test -Wall -I. -lpthread
strip test
运行:
[fens@fens app/test_func_point]$./test
in proc_msg_reg , cmd: 0, data: 注册, data len: 7
in proc_msg_login, cmd: 1, data: 登录, data len: 7
in proc_msg_test , cmd: 2, data: 测试, data len: 7
从上面的打印可以看出,命令字处理的时候都对应到了注册的回调函数。
在实际用时,数据的内容可以是十六进制数据,命令字也可以改为字符串格式。
源代码码云地址:
https://gitee.com/fensnote/demo_code/tree/master/c/test_func_point