函数指针


回调函数

1、函数类型基础

函数三要素:名称、参数、返回值

C语言中的函数有自己特定的类型

C语言中通过typedef为函数类型重命名

typedef type name(parameter list)

typedef int f(int, int);

typedef void p(int);

函数指针

函数指针用于指向一个函数

函数名是执行函数体的入口地址

1)可通过函数类型定义函数指针:FuncType* pointer;

2)也可以直接定义:type(*pointer)(parameter list);

pointer为函数指针变量名

type为指向函数的返回值类型

parameterlist为指向函数的参数类型列表


#include <stdio.h>

typedef int Func(int, int);

typedef int (*PFunc)(int, int);


int add(int a,int b)
{
    return a + b;
}

int main(int argc, char* argv[])
{
    PFunc func = add;
    int res = func(1, 2);
    printf("res = %d\n",res);

    Func *f = add;
    res = (*f)(1, 2);
    printf("res = %d\n",res);

    return 0;
}


2、函数指针做函数参数

  1. 指针做函数参数pk函数指针做函数参数

回忆指针做函数参数

一级指针做函数参数、二级、三级

  1. 函数指针做函数参数

当函数指针做为函数的参数,传递给一个被调用函数,

被调用函数就可以通过这个指针调用外部的函数,这就形成了回调

int add(int a, int b);
void libfun(int (*pDis)(int a, int b));

int main(void)
{
    libfun(add);
    return 0;
}

int add(int a, int b)
{
	return a + b;
}

void libfun(int (*pDis)(int a, intb))
{
    int a, b;
    a = 1;
    b = 2;
    printf("%d", pDis(a, b));
}

现在这几个函数是在同一个文件当中

假如

int libfun(int (*pDis)(int a, intb))

是一个库中的函数,就只有使用回调了,通过函数指针参数将外部函数地址传入

来实现调用


函数add的代码作了修改,也不必改动库的代码,就可以正常实现调用

便于程序的维护和升级


3、函数指针正向调用

  1. 函数指针做函数参数,调用方式

被调用函数和主调函数在同一文件中(用来教学,没有任何意义)

2、函数指针做函数参数

被调用函数和主调函数不在同一个文件中、模块中。

难点:理解被调用函数是什么机制被调用起来的。框架

框架提前设置了被调用函数的入口(框架提供了第三方模块入口地址的集成功能)

框架具备调用第三方模块入口函数

  1. 练习


typedef int (*EncDataFunc)(unsignedchar *inData,int inDataLen,unsigned char *outData,int*outDataLen,void *Ref, int RefLen);


int MyEncDataFunc(unsigned char*inData,int inDataLen,unsigned char *outData,int *outDataLen,void*Ref, int RefLen)

{

int rv = 0;

char *p = "222222222222";

strcpy(outData, p);

*outDataLen = strlen(p);

return rv;

}


int Send_Data(EncDataFuncencDataFunc, unsigned char *inData, int inDataLen, unsigned char*outData, int *outDatalen)

{

int rv = 0;

if (encDataFunc != NULL)

{

rv = encDataFunc(inData,inDataLen, outData, outDatalen, NULL, 0);

if (rv != 0)

{

printf("func encDataFunc()err.\n");

return rv;

}

}

return rv;

}


int main()

{

int rv = 0;


EncDataFunc encDataFunc = NULL;

encDataFunc = MyEncDataFunc;


// 第一个调用

{

unsigned char inData[2048];

int inDataLen;

unsigned char outData[2048];

int outDatalen;

strcpy(inData, "1111");

inDataLen = strlen(inData);

rv = encDataFunc(inData,inDataLen,outData, &outDatalen, NULL, 0);

if (rv != 0)

{

printf("edf err .....\n");

}

else

{

printf("edf ok \n");

printf("%s \n",outData);

}

}


{

unsigned char inData[2048];

int inDataLen;

unsigned char outData[2048];

int outDatalen;

strcpy(inData, "3333");

inDataLen = strlen(inData);

rv = Send_Data(MyEncDataFunc,inData, inDataLen, outData, &outDatalen);

if (rv != 0)

{

printf("func Send_Dataerr:%d", rv);

return rv;

}

printf("%s \n",outData);

}


getchar();

}

4、函数指针反向调用

回调函数

利用函数指针实现的一种调用机制

具体任务的实现者,可以不知道什么时候被调用

回调函数是利用函数指针实现的一种调用机制


回调机制原理

当具体事件发生时,调用者通过函数指针调用具体函数

回调机制的将调用者和被调函数分开,两者互不依赖

任务的实现和 任务的调用 可以耦合 (提前进行接口的封装和设计)

需要重新审视dll和其他第三方厂商接口之间的关系

动态库可以集成第三方厂商的业务功能

动态库(框架)不经常改动,能兼容后来的业务模型,2010年写的代码能调用2020写的代码,用到多态

动态库和第三方业务模型模块之间 松耦合

//动态库变成框架需要做的工作

//1 第三方业务入口传进来(回调函数的入口地址传进来)


//2 加密解密 业务模型抽象

//实现动态库 加密解密业务模型抽象

通过定义函数指针类型;函数指针做函数参数实现



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值