C语言中,没有interface这个语法,因此上面的代码在C语言中,需要用struct 来实现。具体包括:
- 每个接口函数,需要声明一个单独的函数指针类型;
- 整个interface的方法集,用一个struct来表示,struct的成员为各个函数指针
- 每个文件系统的实现者,各自需要一个struct来表示,这个struct的类型对调用者不可见。各个文件系统有自己的struct结构,彼此互不相同,也互不可见。
- 接口的实现,包括两部分:1)接口函数的实现;2)文件系统的struct实例。这两部分放在一起,构成了接口的实现。我们用一个struct来把这两部分组合在一起。
- 由于各个文件系统的struct结构,对调用者不可见,因此文件系统用void*把自己的struct指针传递给调用者。
具体的代码实现,如下:(为了保持篇幅简洁,只列了open_file和read_file 两个方法)
//fs_interface.h
#ifndef FS_INTERFACE_H
#define FS_INTERFACE_H
// 接口函数指针类型
typedef int (*open_file_fn)(void* pfs, const char* path, int flags);
typedef int (*read_file_fn)(void* pfs, int fd, char* buf, int len);
// 接口方法集
typedef struct fs_methods_t {
open_file_fn open_file;
read_file_fn read_file;
} fs_methods_t;
// 接口的实现体
typedef struct file_system_interface {
void* pfs; // 文件系统的具体实现struct
fs_methods_t* pmethods; // 这个文件系统的具体接口方式实现
} file_system_interface;
// 各个文件系统,通过 register_file_system 将自己注册进内核
// const char* pname; // 文件系统的名称,如ext2, xfs...
int register_file_system(const char* pname, file_system_interface fsi);
上面的代码中,有几个地方需要注意:
1)每个接口函数类型声明中,都比interface中的函数多了一个参数:void* pfs, 这个参数指向具体的文件系统的struct。
这样,内核才能真正对这个struct对象发起调用。
2)file_system_interface 是interface的具体实现体,里面包含2个指针:一个是指向文件系统实现体struct的指针pfs, 另一个指针指向文件系统实现的接口函数的集合。这样,interface就是一个简单的struct,可以像简单变量一样声明、赋值和参数传递,其按值拷贝传递即可,无需传指针引用。