回调函数的用法与注意事项

什么是回调函数

回调函数详解

上述链接对回调函数定义和回调函数执行与主函数的执行顺序做了详细说明,但没有具体应用,我记录的是自己实际应用。

一次项目使用回调函数的需要

提供动态库供用户更方便的操作激光雷达,获取激光雷达的定位信息。客户使用动态库,客户自定义回调函数的实现,只需要将回调函数传入,即可获取想要的数据。而不是使用全局变量获取想要的数据。

int lidar_start(int handler, LidarCallbackFunc cbFunc)
启动雷达开始测距,收到测距信息后将通过cbFunc回调提供给应用层。
返回:0, 成功。<0:失败。
参数:handler:打开设备时返回的句柄,cbFunc:回调函数。
typedef struct LidarMsg {
	unsigned int seq;
	unsigned int  stamp; 
	unsigned int frame_id; //开机运行稳定后, 每扫描产生一圈的数据时圈号加 1

	unsigned int angle_min;   
	unsigned int angle_max;

	unsigned int angle_increment;
	unsigned int time_increment;

	unsigned int scan_time;

	unsigned int range_min;        
	unsigned int range_max;//代表雷达扫描一圈点数

	unsigned int ranges[POINTNUMMAX];//雷达扫描一圈测距,每个下标代表一个测距点
	unsigned int intensities[POINTNUMMAX];
}LidarMsg_T;
typedef int(LidarCallbackFunc )(LidarMsg *msg);
源码实现
  • 动态库

    LidarCallbackFunc* g_cbFunc;

    DWORD WINAPI ThreadFun(LPVOID pM)
    {
    LidarMsg * msg = malloc(sizeof(LidarMsg ));
    while (startThreadFlag)
    {
    //写入实际的内容数据
    ...
    //调用回调函数
    g_cbFunc(&msg);
    }
    free(msg);
    return 0;
    }

    int lidar_start(int handler, LidarCallbackFunc* cbFunc)
    {
    startThreadFlag = 1;
    int offset = 0;
    send(sock, (char*)cmdBuf, offset, 0);

      HANDLE handle = CreateThread(NULL, 0, ThreadFun, NULL, 0, NULL);
      g_cbFunc = cbFunc;
      return 0;
    

    }

  • 客户端调用

    //客户自定义回调函数实现,但是参数必须是一致的。
    int getLidarData(LidarMsg msg)
    {
    //此函数的每次被调用,就是动态库中,数据接收完整后,调用时,被调用的
    //客户可以根据需要将数据,另行处理
    char
    data_copy = malloc(sizeof(char) * 1024);
    memcpy(data_copy, msg->ranges, sizeof(char) * 1024);
    //处理数据
    ...
    free(data_copy);
    return 0;
    }

    int main()
    {
    int ret = lidar_start(sock_fd, getLidarData);
    if (ret)
    {
    printf("start fail\n");
    return -1;
    }
    Sleep(5000);
    }

注意事项
  • 上述情况中,LidarMsg msg;数据在动态库中必须要使用,malloc分配,如果不使用,定义成局部变量,在客户使用时,若直接使用mempcy取数组中的数据,将会有问题。但是使用for循环,取数组中数组,不会有问题。