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

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

新建空项目,命名为RF_Drive,这个作为底层的驱动。

tt.png

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


思路:


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


#define  _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//完成发送报文的时候,进行数据加密
//定义函数指针类型  通过函数指针类型 来约定 厂商 去实现 加密解密函数的原型
typedef int(*EncData)(unsigned char *in, int inlen, unsigned char *out, int *outlen);
typedef int(*DecData)(unsigned char *in, int inlen, unsigned char *out, int *outlen);
typedef struct _Sck_Handle
{
    char    version[16];
    char    ip[16];
    int     port;
    unsigned char *p;
    int         len;
    char        *p2;
}Sck_Handle;
int socketclient_sendAndEnc1(void *handle, unsigned char *buf, int buflen, EncData encDataCallback)
{
    int     ret = 0;
    unsigned char cryptbuf[4096];
    int             cryptbuflen = 4096;
    Sck_Handle  *tmpHandle = NULL;
    if (handle == NULL || buf == NULL || encDataCallback == NULL)
    {
        ret = -1;
        printf("func socketclient_sendAndEnc1() err :%d  check handle == NULL err \n", ret);
        return ret;
    }
    ret = encDataCallback(buf, buflen, cryptbuf, &cryptbuflen); //间接的调用子任务
    if (ret != 0)
    {
        ret = -2;
        printf("func socketclient_sendAndEnc1() err :%d  check handle == NULL err \n", ret);
        return ret;
    }
    tmpHandle = (Sck_Handle *)handle;
    tmpHandle->len = cryptbuflen;
    tmpHandle->p = (unsigned char *)malloc(cryptbuflen);
    if (tmpHandle->p == NULL)
    {
        ret = -3;
        printf("func socketclient_sendAndEnc1() err :%d  mallocerr \n", ret);
        return ret;
    }
    //把加密的明文  缓存到 内存中
    memcpy(tmpHandle->p, cryptbuf, cryptbuflen);
    return 0;
}
//socket客户端环境初始化
int socketclient_init(void **handle)
{
    int         ret = 0;
    Sck_Handle  *tmpHandle = NULL;
    if (handle == NULL)
    {
        ret = -1;
        printf("func socketclient_init() err :%d  check handle == NULL err \n", ret);
        return ret;
    }
    tmpHandle = (Sck_Handle *)malloc(sizeof(Sck_Handle));
    if (tmpHandle == NULL)
    {
        ret = -2;
        printf("func socketclient_init() err :%d  malloc err \n", ret);
        return ret;
    }
    memset(tmpHandle, 0, sizeof(Sck_Handle));
    strcpy(tmpHandle->version, "1.0.0.1");
    strcpy(tmpHandle->ip, "192.168.12.12");
    tmpHandle->port = 8081;
    //间接赋值
    *handle = tmpHandle;
    return ret;
}
//socket报文发送
int socketclient_send(void *handle, unsigned char *buf, int buflen)
{
    int         ret = 0;
    Sck_Handle  *tmpHandle = NULL;
    if (handle == NULL || buf == NULL || buflen <= 0)
    {
        ret = -2;
        printf("func socketclient_send() err :%d  (handle == NULL ||  buf==NULL || buflen <=0 ) \n", ret);
        return ret;
    }
    tmpHandle = (Sck_Handle *)handle;
    tmpHandle->len = buflen;
    tmpHandle->p = (unsigned char *)malloc(buflen);
    if (tmpHandle->p == NULL)
    {
        ret = -2;
        printf("func socketclient_send() err :%d  malloc len:%d \n", ret, buflen);
        return ret;
    }
    memcpy(tmpHandle->p, buf, buflen); //数据的缓存到内存
    return ret;
}
//socket报文接受
int socketclient_recv(void *handle, unsigned char *buf, int *buflen)
{
    int         ret = 0;
    Sck_Handle  *tmpHandle = NULL;
    if (handle == NULL || buf == NULL || buflen == NULL)
    {
        ret = -2;
        printf("func socketclient_recv() err :%d  (handle == NULL ||  buf==NULL || buflen==NULL ) \n", ret);
        return ret;
    }
    tmpHandle = (Sck_Handle *)handle;
    memcpy(buf, tmpHandle->p, tmpHandle->len);
    *buflen = tmpHandle->len; //间接赋值  告诉调用者 收到的数据的长度
    return ret;
}
//socket环境释放
int socketclient_destory(void *handle)
{
    int         ret = 0;
    Sck_Handle  *tmpHandle = NULL;
    if (handle == NULL)
    {
        return -1;
    }
    tmpHandle = (Sck_Handle *)handle;
    if (tmpHandle->p != NULL)
    {
        free(tmpHandle->p); //释放结构体 成员域的 指针所指向的内存空间
    }
    free(tmpHandle); //释放结构体内存
    return 0;
}
  1. 添加MyDrive.h文件。

 

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

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

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

#ifndef _INC_MYDRIVE_H__
#define _INC_MYDRIVE_H__
#define Import_SSS
#ifdef Import_SSS
#define API _declspec(dllexport)
#else
#define API _declspec(dllimport)
#endif
#ifdef  __cplusplus
extern "C" {
#endif
    //1 数据类型的封装
    //2 handle的概念:  底层库的内存资源,记录着函数运行的上下文信息..
    //3 底层库提供的是一种机制, 而不是满足某一个人的策略
    //完成发送报文的时候,进行数据加密
    //定义函数指针类型  通过函数指针类型 来约定 厂商 去实现 加密解密函数的原型
    typedef int(*EncData)(unsigned char *in, int inlen, unsigned char *out, int *outlen);
    typedef int(*DecData)(unsigned char *in, int inlen, unsigned char *out, int *outlen);
    API
        int socketclient_init(void **handle);
    API
        int socketclient_send(void *handle, unsigned char *buf, int buflen);
    API
        int socketclient_sendAndEnc1(void *handle, unsigned char *buf, int buflen, EncData encDataCallback);
    API
        int socketclient_recv(void *handle, unsigned char *buf, int *buflen);
    API
        int socketclient_destory(void *handle);
#ifdef  __cplusplus
 }
#endif
#endif
目录
相关文章
|
3月前
|
Unix
网络编程之 信号捕捉器(函数指针与回调函数)(2)
sigaction()函数 前面我们讲到的内容已经足以用来防止僵尸进程生成的代码。之所以博主还要介绍sigaction()函数是因为它类似于signal()函数,而且完全可以代替后者,也更稳定(主要是书上介绍到了
31 1
|
3月前
|
Linux
网络编程之 信号捕捉器(函数指针与回调函数)(1)
接着我们的信号说下去 之前博主给大家分享到了信号的概念和初步介绍signal函数的形式后就没有继续往下介绍了,实在是因为时间不够,那个时候博主还要上课,现在博主放假了就好好给大家分享一下如何注册信号捕捉,以及信号捕捉器的妙用。
34 1
|
1月前
|
存储 C语言
c语言函数指针和指针函数的区别,以及回调函数的使用。
c语言函数指针和指针函数的区别,以及回调函数的使用。
9 0
|
1月前
|
存储 程序员 API
C函数指针与回调函数
C函数指针与回调函数
25 0
|
2月前
|
C语言 C++
C语言之指针进阶篇_回调函数(3)
C语言之指针进阶篇_回调函数(3)
22 0
|
3月前
|
编译器 C++
函数指针和回调函数对函数取地址和直接使用函数名的差距
函数指针和回调函数对函数取地址和直接使用函数名的差距
39 0
|
4月前
|
存储
指针详解(冒泡排序、qsort、回调函数、转移表)(三)
指针详解(冒泡排序、qsort、回调函数、转移表)(三)
|
4月前
函数指针和回调函数
简介 函数的二进制代码存放在内存四区中的代码区,函数的地址是它在内存中的起始地址。如果把函数的地址作为参数传递给函数,就可以在函数中灵活的调用其它函数。 使用函数指针的三个步骤: 1.声明函数指针: 声明普通指针时,必须提供指针的类型。同样,声明函数指针时,也必须提供函数类型,函数的类型是指返回值和参数列表(函数名和形参名不是) 函数之间具有相同的返回值类型和参数列表数目和类型都相同即是同一类函数
23 0
|
5月前
|
编译器 C语言
【C语言】指针的进阶(二)—— 回调函数的讲解以及qsort函数的使用方式
【C语言】指针的进阶(二)—— 回调函数的讲解以及qsort函数的使用方式
12 0
|
5月前
【指针的进阶(3)】回调函数和qsort排序各种类型的数据
【指针的进阶(3)】回调函数和qsort排序各种类型的数据
34 0