10.C 语言结构体:面向对象思想的嵌入式实践

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;