C语言结构体模拟面向对象的核心方法
结构体封装数据与行为 通过定义结构体承载对象状态(如设备配置、缓冲区)和函数指针(如ops),将数据与操作绑定。例如:
c
typedef struct {
void (*send)(void* ctx, uint8_t* data);
void (*receive)(void* ctx);
} uart_ops_t;
typedef struct {
uint32_t baudrate;
uart_ops_t* ops;
} uart_dev_t;
函数指针实现多态 不同设备实例可绑定不同的函数实现。例如针对STM32和ESP32的差异化驱动:
c
// STM32实现
void stm32_uart_send(void* ctx, uint8_t* data) {
USART1->DR = *data;
}
// ESP32实现
void esp32_uart_send(void* ctx, uint8_t* data) {
uart_write_bytes(UART_NUM_0, data, 1);
}
Handle机制控制访问边界 通过不透明指针限制内部访问,仅暴露接口:
c
typedef void* uart_handle_t;
uart_handle_t uart_create(void);
void uart_send(uart_handle_t h, uint8_t* data);
嵌入式实践中的典型应用场景
设备驱动抽象层 定义统一操作接口,适配不同硬件:
c
typedef struct {
int (*init)(void* ctx);
int (*read)(void* ctx, uint8_t* buf);
} sensor_driver_t;
// 温度传感器实例
sensor_driver_t tmp112_driver = {
.init = tmp112_init,
.read = tmp112_read
};
协议栈实现 通过结构体管理协议状态机:
c
typedef struct {
uint8_t state;
void (*parse)(modbus_ctx_t* ctx);
void (*build_response)(modbus_ctx_t* ctx);
} modbus_ctx_t;
关键设计原则
单一职责原则 每个结构体应只承担单一功能,如:
uart_cfg_t仅含配置参数uart_stats_t仅记录运行统计uart_ops_t仅定义操作接口
开闭原则设计 通过函数指针扩展,避免修改核心逻辑:
c
typedef struct {
void (*error_handler)(void* ctx, int err);
} uart_ext_ops_t;
依赖倒置原则 高层模块依赖抽象接口:
c
void data_logger_init(logger_ops_t* ops) {
// 不关心具体存储介质
ops->write(...);
}
性能优化技巧
内存布局优化 使用__attribute__((packed))减少内存占用:
c
typedef struct __attribute__((packed)) {
uint8_t addr;
uint16_t value;
} modbus_reg_t;
内联关键方法 对性能敏感的函数声明为内联:
c
static inline void fifo_push(fifo_t* f, uint8_t data) {
f->buf[f->head++] = data;
}
错误处理模式
状态码封装 统一错误代码定义:
c
typedef enum {
DRV_OK,
DRV_BUSY,
DRV_TIMEOUT
} drv_status_t;
drv_status_t uart_send(uart_handle_t h, ...);
错误回调机制 通过函数指针注册错误处理:
c
typedef struct {
void (*on_error)(int err_code, void* arg);
} event_callbacks_t;
实例:GPIO对象化实现
接口定义
c
typedef struct {
void (*set)(void* ctx, bool state);
bool (*get)(void* ctx);
void (*toggle)(void* ctx);
} gpio_ops_t;
typedef struct {
uint8_t pin;
gpio_ops_t* ops;
} gpio_dev_t;
具体实现
c
// STM32实现
void stm32_gpio_set(void* ctx, bool state) {
gpio_dev_t* dev = ctx;
HAL_GPIO_WritePin(dev->pin, state?GPIO_PIN_SET:GPIO_PIN_RESET);
}
// 使用示例
gpio_ops_t stm32_ops = {.set = stm32_gpio_set};
gpio_dev_t led = {.pin = GPIO_PIN_5, .ops = &stm32_ops};
led.ops->set(&led, true);
测试验证方法
接口mock测试
c
// 测试用的mock实现
void mock_gpio_set(void* ctx, bool state) {
printf("GPIO set to %d\n", state);
}
void test_gpio() {
gpio_ops_t mock_ops = {.set = mock_gpio_set};
gpio_dev_t dev = {.ops = &mock_ops};
dev.ops->set(&dev, true); // 验证输出
}
资源管理规范
引用计数
c
typedef struct {
int ref_count;
void* resource;
} res_handle_t;
void res_acquire(res_handle_t* h) {
h->ref_count++;
}
void res_release(res_handle_t* h) {
if(--h->ref_count == 0) {
free(h->resource);
}
}
跨平台兼容方案
条件编译适配
c
typedef struct {
#ifdef USE_HAL_DRIVER
UART_HandleTypeDef* huart;
#elif defined(ESP_IDF)
uart_port_t uart_num;
#endif
} uart_platform_t;