一点五编程 细节补充
在interface接口层的设计中 所有的形参都是void*类型 指代任何结构体,在硬件实现层时形参为该硬件结构体的实例
typedef int (*light_on_fn_t)(void* self);
typedef int (*light_off_fn_t)(void* self);
struct light_i
{
light_on_fn_t light_on;
light_off_fn_t light_off;
};
上面时接口层.函数的形参为void *self
int io_led_on(struct io_led* self);
int io_led_off(struct io_led* self);
struct light_i io_led_interface = {
.light_on = (light_on_fn_t) io_led_on,
.light_off = (light_off_fn_t) io_led_off,
};
上面时io_led硬件实现层,形参时struct io_led* self
通过(light_on_fn_t) io_led_on强制转换 将硬件结构体传入接口函数内
接口函数封装
在struct工程中 没有将接口进行封装 虽然实现了(*p)->f§的效果 但使用的时候不够直观 看起来比较抽象
static inline int light_on(void* self)
{
return (*(struct light_i**)self)->light_on(self);
}
static inline int light_off(void* self)
{
return (*(struct light_i**)self)->light_off(self);
}
static inline int light_get_status(void* self)
{
return (*(struct light_i**)self)->light_get_status(self);
}
在接口层中light.h将函数进行封装 可以看到在返回return里面是(*p)->f(p)
这里封装的时候时在接口层light.h中进行封装 其形参是void *self
所以该函数可以通用,实现多态的效果.
其真正实现的接口函数 根据传入的形参地址去找寻
实现效果如下
// 定义两个结构体
struct light_i {
void (*light_open)(struct light_i *self);
void (*light_close)(struct light_i *self);
};
struct io_led {
struct light_i interface; // 必须位于结构体的开始位置
int status;
const char *name;
};
// 创建一个 io_led 实例
struct io_led light1;
struct io_led light2;
//调用统一接口函数 如on、off、open、close
light_on(light1);
light_off(light2);
delay(100);
light_off(light1);
light_on(light2);
delay(100);