回调函数的理解和例子
嵌入式设备对象管理案例分析与实现
代码分析
这是一个嵌入式系统中设备对象管理的结构体设计,采用了面向对象的思想在C语言中实现。让我通过一个简单的LED控制案例来详细解释。
案例:LED设备控制
1. 定义设备结构体和回调函数类型
#include <stdio.h>
#include <stdint.h>
#include <string.h>// 定义回调函数类型
typedef void (*run_t)(void* argument);// 定义回调函数数量
#define CALLBACKCOUNT 6// 设备对象结构体
struct OBJ_DEV_T
{char instance_name[16]; // 实例名称uint8_t is_initialized; // 初始化状态标志run_t function[CALLBACKCOUNT]; // 回调函数数组uint8_t funskip; // 函数跳过标志// 对外方法封装struct{void (*InitHardWare)(void); // 初始化硬件void (*InitDeHardWare)(void); // 反初始化硬件void (*Wakup)(struct OBJ_DEV_T* DevInst); // 唤醒设备void (*Sleep)(struct OBJ_DEV_T* DevInst); // 休眠设备void (*Run)(struct OBJ_DEV_T* DevInst, const char *name, void* argument); // 运行函数void (*CreateRun)(struct OBJ_DEV_T* DevInst, const char *name, void (*fun)(void* argument)); // 创建运行函数} method;
};
2. 创建LED控制回调函数
// LED开启回调函数
void LED_On(void* argument) {printf("LED turned ON\n");// 实际硬件操作代码会在这里
}// LED关闭回调函数
void LED_Off(void* argument) {printf("LED turned OFF\n");// 实际硬件操作代码会在这里
}// LED闪烁回调函数
void LED_Blink(void* argument) {int times = *(int*)argument;printf("LED blinking %d times\n", times);// 实际硬件操作代码会在这里
}
3. 实现设备对象创建函数
// 设备对象创建函数
struct OBJ_DEV_T* CreateOBJ_DEV(const char* name, run_t* callbacks) {// 分配内存struct OBJ_DEV_T* new_dev = (struct OBJ_DEV_T*)malloc(sizeof(struct OBJ_DEV_T));// 设置实例名称strncpy(new_dev->instance_name, name, 15);new_dev->instance_name[15] = '\0'; // 确保字符串终止// 初始化标志new_dev->is_initialized = 0;new_dev->funskip = 0;// 设置回调函数if(callbacks) {for(int i = 0; i < CALLBACKCOUNT; i++) {new_dev->function[i] = callbacks[i];}}return new_dev;
}
4. 实现方法函数
// 初始化硬件方法
void InitHardWareImpl(void) {printf("Hardware initialized\n");
}// 反初始化硬件方法
void InitDeHardWareImpl(void) {printf("Hardware deinitialized\n");
}// 唤醒设备方法
void WakeupImpl(struct OBJ_DEV_T* DevInst) {printf("Device %s woken up\n", DevInst->instance_name);
}// 休眠设备方法
void SleepImpl(struct OBJ_DEV_T* DevInst) {printf("Device %s put to sleep\n", DevInst->instance_name);
}// 运行指定函数方法
void RunImpl(struct OBJ_DEV_T* DevInst, const char *name, void* argument) {printf("Running function %s on device %s\n", name, DevInst->instance_name);// 在实际应用中,这里会根据名称查找并执行对应的回调函数if(strcmp(name, "LED_On") == 0) {LED_On(argument);} else if(strcmp(name, "LED_Off") == 0) {LED_Off(argument);} else if(strcmp(name, "LED_Blink") == 0) {LED_Blink(argument);}
}// 创建运行函数方法
void CreateRunImpl(struct OBJ_DEV_T* DevInst, const char *name, void (*fun)(void* argument)) {printf("Creating run function %s for device %s\n", name, DevInst->instance_name);// 在实际应用中,这里会将函数指针存储到回调函数数组中// 这里简化处理,只是打印信息
}
5. 初始化回调函数数组
// 初始化回调函数数组
void OBJ_Callback_init(run_t* callbacks) {// 初始化回调函数数组,这里简单设置为NULLfor(int i = 0; i < CALLBACKCOUNT; i++) {callbacks[i] = NULL;}
}
6. 主函数演示使用流程
int main() {printf("=== LED设备控制演示 ===\n\n");// 1. 初始化回调函数数组run_t callbacks[CALLBACKCOUNT];OBJ_Callback_init(callbacks);// 2. 创建设备实例printf("步骤1: 创建设备实例\n");struct OBJ_DEV_T* LED_Device = CreateOBJ_DEV("LEDDevice", callbacks);printf("创建了设备: %s\n\n", LED_Device->instance_name);// 3. 设置设备方法printf("步骤2: 设置设备方法\n");LED_Device->method.InitHardWare = InitHardWareImpl;LED_Device->method.InitDeHardWare = InitDeHardWareImpl;LED_Device->method.Wakup = WakeupImpl;LED_Device->method.Sleep = SleepImpl;LED_Device->method.Run = RunImpl;LED_Device->method.CreateRun = CreateRunImpl;printf("设备方法设置完成\n\n");// 4. 初始化硬件printf("步骤3: 初始化硬件\n");LED_Device->method.InitHardWare();LED_Device->is_initialized = 1;printf("\n");// 5. 创建设备运行函数printf("步骤4: 创建设备运行函数\n");LED_Device->method.CreateRun(LED_Device, "LED_On", LED_On);LED_Device->method.CreateRun(LED_Device, "LED_Off", LED_Off);LED_Device->method.CreateRun(LED_Device, "LED_Blink", LED_Blink);printf("\n");// 6. 运行设备函数printf("步骤5: 运行设备函数\n");int blink_times = 5;LED_Device->method.Run(LED_Device, "LED_On", NULL);LED_Device->method.Run(LED_Device, "LED_Blink", &blink_times);LED_Device->method.Run(LED_Device, "LED_Off", NULL);printf("\n");// 7. 休眠设备printf("步骤6: 休眠设备\n");LED_Device->method.Sleep(LED_Device);printf("\n");// 8. 唤醒设备printf("步骤7: 唤醒设备\n");LED_Device->method.Wakup(LED_Device);printf("\n");// 9. 反初始化硬件printf("步骤8: 反初始化硬件\n");LED_Device->method.InitDeHardWare();printf("\n");printf("=== 演示结束 ===\n");// 释放内存free(LED_Device);return 0;
}