欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言工作笔记-对函数指针的进一步认识(与回调函数结合使用,并且对比C++的回调)

程序员文章站 2022-07-13 22:06:45
...

目录

 

背景和基本概念(含与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;
}

运行截图如下:

C语言工作笔记-对函数指针的进一步认识(与回调函数结合使用,并且对比C++的回调)

但这样的函数指针并不能提现他真正方便的地方!

下面说下他正在方便的地方!

 

函数指针结合回调

这里其实可以把函数指针理解为变量,如下代码:

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;

C语言工作笔记-对函数指针的进一步认识(与回调函数结合使用,并且对比C++的回调)

如下最基础的,模块注册,模块管理,根据函数指针回调的例子!

运行截图如下:

C语言工作笔记-对函数指针的进一步认识(与回调函数结合使用,并且对比C++的回调)

程序结构如下:

C语言工作笔记-对函数指针的进一步认识(与回调函数结合使用,并且对比C++的回调)

源码如下:

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