C语言工作笔记-对函数指针的进一步认识(与回调函数结合使用,并且对比C++的回调)
目录
背景和基本概念(含与C++回调对比)
毕业也有10个月了,加上实习已经工作14个月了,感觉这一年多的板砖生涯学到了很多的东西。同样本人对函数指针又有了新的认识。原因是这个月在某平台上进行二次开发,发现这里面有很多的callback!这个callback并不是C++里的callback,而是C语言的Callback。
估计是开发这个平台的人喜欢C语言的Callback,而不喜欢C++的Callback。
这里我简单说明下我对这两种Callback体会:
在我这边的项目中,我接触过2种不同的回调!
一种是C语言的,他的回调方式是使用函数指针。通常会有一个注册函数,把要回调的函数注册进去,之后就通过函数指针进行调用,这种是我最近才接触到的。
还有一种回调是C++的回调。这个在项目里面接触得比较多,毕竟现在我就是C++开发工程师(虽然有时候也做Java和DBA的工作),这种回调感觉比C语言的回调更加的灵活。这种一般是类继承的概念,一般用纯虚类使用纯虚函数充当接口(也有用一般的类,用虚函数做接口的),用虚函数的特点使用父类指针调用子类对象。感觉C++的回调,还是比C语言灵活的。
下面将说明下C语言中函数指针结合回调函数的用法;
函数指针最一般的用法
下面给出函数指针最一般的用法,估计稍微学过C语言语法的学生都会使用:
#include <stdio.h>
int Sum(int a, int b){
return a + b;
}
int main(int argc, int **argv){
int (*pFun)(int a, int b);
pFun = Sum;
printf("Sum=%d\n", pFun(100, 200));
getchar();
return 0;
}
运行截图如下:
但这样的函数指针并不能提现他真正方便的地方!
下面说下他正在方便的地方!
函数指针结合回调
这里其实可以把函数指针理解为变量,如下代码:
int (*fun1)(char);
int *(*fun2)(char);
int (*fun3[])(char);
int *(*fun4[])(char);
typedef int(*pProcFun)(char);
pProcFun pFun1;
pProcFun pFun3[];
pProcFun *pFun3ptr;
pProcFun pFun2;
pProcFun pFun4[];
pProcFun *pFun4ptr;
如下最基础的,模块注册,模块管理,根据函数指针回调的例子!
运行截图如下:
程序结构如下:
源码如下:
FirstModule.h
#pragma once
#include "stdef.h"
#include "moduleAdmin.h"
int InitFirstModule();
moduleAdmin.h
#pragma once
#include "stdef.h"
typedef enum tagMODULE_SETS //SETS表示这是枚举集合
{
MY_ALL_MODULE = 0,
MY_READ_MODULE = 1,
MY_WRITE_MODULE = 2,
MY_INVALID_MODULE = 0xffff
}MODULE_SETS_E; //E表示enum
typedef int(*pProcFun)();
typedef struct tagMoudleData //一般带有管理的结构体在C语言中都是tagXXXX
{
int iModule; //每个模块唯一ID
pProcFun pFun;
}MOUDLE_DATA_S; //一般在结构体结尾都加S,代表struct;
int RegisterProc(int iModule, pProcFun pFun);
int ExcuteAllModule();
SecondMoudle.h
#pragma once
#include "stdef.h"
#include "moduleAdmin.h"
int InitSecondModule();
stdef.h
#pragma once
#include <stdio.h>
#include <Windows.h>
#define OK 0
#define ERR -1
FirstModule.cpp
#include "FirstModule.h"
int FirstModuleProc(){
printf("Hello I am First Module\n");
return OK;
}
int InitFirstModule(){
RegisterProc(MY_WRITE_MODULE, FirstModuleProc);
return OK;
}
main.cpp
#include "stdef.h"
#include "FirstModule.h"
#include "SecondModule.h"
DWORD WINAPI MyThread(){
while(1){
ExcuteAllModule();
Sleep(1000);
}
}
int TestFunPtr(){
InitFirstModule();
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MyThread, NULL, 0, NULL);
Sleep(3000);
InitSecondModule();
Sleep(3000);
TerminateThread(hThread, 0);
CloseHandle(hThread);
return OK;
}
int main(int argc, int *argv[]){
TestFunPtr();
getchar();
return 0;
}
moduleAdmin.cpp
#include "moduleAdmin.h"
#define MAX_PROC 100
int g_iProCnt = 0; //全局的前面加一个g
MOUDLE_DATA_S FunList[MAX_PROC] = {0};
int RegisterProc(int iModule, pProcFun pFun){
if(g_iProCnt == MAX_PROC){
return ERR;
}
FunList[g_iProCnt].iModule = iModule;
FunList[g_iProCnt].pFun = pFun;
g_iProCnt++;
return OK;
}
//调用注册的函数
int ExcuteAllModule(){
for(int i = 0; i < g_iProCnt; i++){
FunList[i].pFun();
}
return OK;
}
SecondModule.cpp
#include "SecondModule.h"
int SecondModuleProc(){
printf("Hello I am Second Module\n");
return OK;
}
int InitSecondModule(){
RegisterProc(MY_READ_MODULE, SecondModuleProc);
return OK;
}
源码打包
下载地址:
https://github.com/fengfanchen/CAndCPP/tree/master/CfunctionPtrAndCallBack