利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦

举报
AI浩 发表于 2021/12/22 23:42:38 2021/12/22
【摘要】 新建空项目,命名为RF_Drive,这个作为底层的驱动。 添加MyDrive.c文件,向文件中添加代码,模拟驱动一些函数,代码如下:   思路: EncData和DecData实现信息的加密和解密,由于不同厂家的设备,加密和解密的方式不同,所以不能在底层驱动中实现,需要不同的厂家在自己的函数库中实现。厂家和驱动约定好相...
  1. 新建空项目,命名为RF_Drive,这个作为底层的驱动。

  1. 添加MyDrive.c文件,向文件中添加代码,模拟驱动一些函数,代码如下:

 

思路:

EncData和DecData实现信息的加密和解密,由于不同厂家的设备,加密和解密的方式不同,所以不能在底层驱动中实现,需要不同的厂家在自己的函数库中实现。厂家和驱动约定好相同的接口,将函数通过指针传进来,实现函数的回调。


  
  1. #define  _CRT_SECURE_NO_WARNINGS
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. //完成发送报文的时候,进行数据加密
  6. //定义函数指针类型  通过函数指针类型 来约定 厂商 去实现 加密解密函数的原型
  7. typedef int(*EncData)(unsigned char *in, int inlen, unsigned char *out, int *outlen);
  8. typedef int(*DecData)(unsigned char *in, int inlen, unsigned char *out, int *outlen);
  9. typedef struct _Sck_Handle
  10. {
  11.     char    version[16];
  12.     char    ip[16];
  13.     int     port;
  14.     unsigned char *p;
  15.     int         len;
  16.     char        *p2;
  17. }Sck_Handle;
  18. int socketclient_sendAndEnc1(void *handle, unsigned char *buf, int buflen, EncData encDataCallback)
  19. {
  20.     int     ret = 0;
  21.     unsigned char cryptbuf[4096];
  22.     int             cryptbuflen = 4096;
  23.     Sck_Handle  *tmpHandle = NULL;
  24.     if (handle == NULL || buf == NULL || encDataCallback == NULL)
  25.     {
  26.         ret = -1;
  27.         printf("func socketclient_sendAndEnc1() err :%d  check handle == NULL err \n", ret);
  28.         return ret;
  29.     }
  30.     ret = encDataCallback(buf, buflen, cryptbuf, &cryptbuflen); //间接的调用子任务
  31.     if (ret != 0)
  32.     {
  33.         ret = -2;
  34.         printf("func socketclient_sendAndEnc1() err :%d  check handle == NULL err \n", ret);
  35.         return ret;
  36.     }
  37.     tmpHandle = (Sck_Handle *)handle;
  38.     tmpHandle->len = cryptbuflen;
  39.     tmpHandle->p = (unsigned char *)malloc(cryptbuflen);
  40.     if (tmpHandle->p == NULL)
  41.     {
  42.         ret = -3;
  43.         printf("func socketclient_sendAndEnc1() err :%d  mallocerr \n", ret);
  44.         return ret;
  45.     }
  46.     //把加密的明文  缓存到 内存中
  47.     memcpy(tmpHandle->p, cryptbuf, cryptbuflen);
  48.     return 0;
  49. }
  50. //socket客户端环境初始化
  51. int socketclient_init(void **handle)
  52. {
  53.     int         ret = 0;
  54.     Sck_Handle  *tmpHandle = NULL;
  55.     if (handle == NULL)
  56.     {
  57.         ret = -1;
  58.         printf("func socketclient_init() err :%d  check handle == NULL err \n", ret);
  59.         return ret;
  60.     }
  61.     tmpHandle = (Sck_Handle *)malloc(sizeof(Sck_Handle));
  62.     if (tmpHandle == NULL)
  63.     {
  64.         ret = -2;
  65.         printf("func socketclient_init() err :%d  malloc err \n", ret);
  66.         return ret;
  67.     }
  68.     memset(tmpHandle, 0, sizeof(Sck_Handle));
  69.     strcpy(tmpHandle->version, "1.0.0.1");
  70.     strcpy(tmpHandle->ip, "192.168.12.12");
  71.     tmpHandle->port = 8081;
  72.     //间接赋值
  73.     *handle = tmpHandle;
  74.     return ret;
  75. }
  76. //socket报文发送
  77. int socketclient_send(void *handle, unsigned char *buf, int buflen)
  78. {
  79.     int         ret = 0;
  80.     Sck_Handle  *tmpHandle = NULL;
  81.     if (handle == NULL || buf == NULL || buflen <= 0)
  82.     {
  83.         ret = -2;
  84.         printf("func socketclient_send() err :%d  (handle == NULL ||  buf==NULL || buflen <=0 ) \n", ret);
  85.         return ret;
  86.     }
  87.     tmpHandle = (Sck_Handle *)handle;
  88.     tmpHandle->len = buflen;
  89.     tmpHandle->p = (unsigned char *)malloc(buflen);
  90.     if (tmpHandle->p == NULL)
  91.     {
  92.         ret = -2;
  93.         printf("func socketclient_send() err :%d  malloc len:%d \n", ret, buflen);
  94.         return ret;
  95.     }
  96.     memcpy(tmpHandle->p, buf, buflen); //数据的缓存到内存
  97.     return ret;
  98. }
  99. //socket报文接受
  100. int socketclient_recv(void *handle, unsigned char *buf, int *buflen)
  101. {
  102.     int         ret = 0;
  103.     Sck_Handle  *tmpHandle = NULL;
  104.     if (handle == NULL || buf == NULL || buflen == NULL)
  105.     {
  106.         ret = -2;
  107.         printf("func socketclient_recv() err :%d  (handle == NULL ||  buf==NULL || buflen==NULL ) \n", ret);
  108.         return ret;
  109.     }
  110.     tmpHandle = (Sck_Handle *)handle;
  111.     memcpy(buf, tmpHandle->p, tmpHandle->len);
  112.     *buflen = tmpHandle->len; //间接赋值  告诉调用者 收到的数据的长度
  113.     return ret;
  114. }
  115. //socket环境释放
  116. int socketclient_destory(void *handle)
  117. {
  118.     int         ret = 0;
  119.     Sck_Handle  *tmpHandle = NULL;
  120.     if (handle == NULL)
  121.     {
  122.         return -1;
  123.     }
  124.     tmpHandle = (Sck_Handle *)handle;
  125.     if (tmpHandle->p != NULL)
  126.     {
  127.         free(tmpHandle->p); //释放结构体 成员域的 指针所指向的内存空间
  128.     }
  129.     free(tmpHandle); //释放结构体内存
  130.     return 0;
  131. }
  1. 添加MyDrive.h文件。

 

完成后,右键项目,将配置类型改为dll动态链接库。

  1. 新建TestDrive工程,测试底层dll。将生成的RF_Drive.dll、RF_Drive.lib和MyDrive.h文件放到工程目录下面。

  1. 将RF_Drive链接到TestDrive。选择输入,然后选择附加依赖项,将RF_Drive.lib添加进去,然后点击确定。

  1. 将MyDrive.h包含到项目,然后新建Test.c文件,在Test.c中写入测试代码。代码如下:

  
  1. #ifndef _INC_MYDRIVE_H__
  2. #define _INC_MYDRIVE_H__
  3. #define Import_SSS
  4. #ifdef Import_SSS
  5. #define API _declspec(dllexport)
  6. #else
  7. #define API _declspec(dllimport)
  8. #endif
  9. #ifdef  __cplusplus
  10. extern "C" {
  11. #endif
  12.     //1 数据类型的封装
  13.     //2 handle的概念:  底层库的内存资源,记录着函数运行的上下文信息..
  14.     //3 底层库提供的是一种机制, 而不是满足某一个人的策略
  15.     //完成发送报文的时候,进行数据加密
  16.     //定义函数指针类型  通过函数指针类型 来约定 厂商 去实现 加密解密函数的原型
  17.     typedef int(*EncData)(unsigned char *in, int inlen, unsigned char *out, int *outlen);
  18.     typedef int(*DecData)(unsigned char *in, int inlen, unsigned char *out, int *outlen);
  19.     API
  20.         int socketclient_init(void **handle);
  21.     API
  22.         int socketclient_send(void *handle, unsigned char *buf, int buflen);
  23.     API
  24.         int socketclient_sendAndEnc1(void *handle, unsigned char *buf, int buflen, EncData encDataCallback);
  25.     API
  26.         int socketclient_recv(void *handle, unsigned char *buf, int *buflen);
  27.     API
  28.         int socketclient_destory(void *handle);
  29. #ifdef  __cplusplus
  30.  }
  31. #endif
  32. #endif

思路:

在调用者实现加密算法Hw_EncData,不同的调用者,实现加密算法的方式不同,需要调用者自己实现,然后将函数的指针传递给底层驱动。


  
  1. #define  _CRT_SECURE_NO_WARNINGS
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include "MyDrive.h"
  6. int Hw_EncData(unsigned char *in, int inlen, unsigned char *out, int *outlen)
  7. {
  8.     printf("func Hw_EncData begin....\n ");
  9.     strcpy((char *)out, "123456789");
  10.     *outlen = 9;
  11.     printf("func Hw_EncData end....\n ");
  12.     return 0;
  13. }
  14. void main()
  15. {
  16.     unsigned char buf[1024];
  17.     int buflen;
  18.     unsigned char out[1024];
  19.     int outlen;
  20.     void *handle = NULL;
  21.     int ret = 0;
  22.     strcpy((char *)buf, "aaaaaaaaaffffffffdddddddd");
  23.     buflen = 9;
  24.     //客户端初始化 获取handle上下
  25.     ret = socketclient_init(&handle /*out*/);
  26.     if (ret != 0)
  27.     {
  28.         printf("func socketclient_init() err:%d \n ", ret);
  29.         goto End;
  30.     }
  31.     //客户端发报文
  32.     //ret = socketclient_send(handle /*in*/, buf /*in*/,  buflen /*in*/);
  33.     ret = socketclient_sendAndEnc1(handle, buf, buflen, Hw_EncData);
  34.     if (ret != 0)
  35.     {
  36.         printf("func socketclient_send() err:%d \n ", ret);
  37.         goto End;
  38.     }
  39.     //客户端收报文
  40.     ret = socketclient_recv(handle /*in*/, out /*in*/, &outlen/*in out*/);
  41.     if (ret != 0)
  42.     {
  43.         printf("func socketclient_recv() err:%d \n ", ret);
  44.         goto End;
  45.     }
  46. End:
  47.     //客户端释放资源
  48.     ret = socketclient_destory(handle/*in*/);
  49.     printf("hello...\n");
  50.     system("pause");
  51.     printf("hello...\n");
  52.     system("pause");
  53.     return;
  54. }

运行结果如下:

代码:https://download.csdn.net/download/hhhhhhhhhhwwwwwwwwww/12898322

文章来源: wanghao.blog.csdn.net,作者:AI浩,版权归原作者所有,如需转载,请联系作者。

原文链接:wanghao.blog.csdn.net/article/details/108870746

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。