# 接口

在一些设备类型定义中我们可以看到interfaces一栏。

```
static TypeInfo pc_dimm_info = {
    .name          = TYPE_PC_DIMM,
    .parent        = TYPE_DEVICE,
    ...
    .interfaces = (InterfaceInfo[]) {
        { TYPE_MEMORY_DEVICE },
        { }
    },
};
```

那这一栏是什么意思呢？让我们来进一步打开看看。

## Interface也是一种类型

进一步看，可以发现在Qemu模型中接口也是一种类型，并且也有父子关系。

```
static TypeInfo interface_info = {
    .name = TYPE_INTERFACE,
    .class_size = sizeof(InterfaceClass),
    .abstract = true,
};

static const TypeInfo memory_device_info = {
    .name          = TYPE_MEMORY_DEVICE,
    .parent        = TYPE_INTERFACE,
    .class_size = sizeof(MemoryDeviceClass),
};
```

但是和普通类型不同，他们只有对应的Class，而没有object。

我们尝试把这两个类型画成图，或许能看得更清楚一些。

```
                                              +---------------------------------------------------------------+
                                              |                                                               |
                                              v                                                               |
       TypeInfo                               TypeImpl*                       InterfaceClass                  |
       +---------------------+                +----------------------+    +-->+------------------------+      |
       |name                 | type_new()---> |name                  |    |   |parent_class            |      |
       |     TYPE_INTERFACE  |                |    TYPE_INTERFACE    |    |   |   (ObjectClass)        |      |
       +---------------------+                |class              ---|----+   |   type             ----|------+
                                              |    (ObjectClass*)    |        |concrete_class          |
                                              +----------------------+        |   (ObjectClass*)       |
                                                                              |interface_type          |
                                                                              |   (TypeImpl*)          |
                                                                              +------------------------+
                                                                                    |
                                                                                    |
                                                                                    |
                                                                                    v
                                              +---------------------------------------------------------------+
                                              |                                MemoryDeviceClass              |
                                              v                                +--------------------------+   |
       TypeInfo                               TypeImpl*                        |InterfaceClass            |   |
       +---------------------+                +----------------------+    +--> | +------------------------+   |
       |name                 | type_new()---> |name                  |    |    | |parent_class            |   |
       |   TYPE_MEMORY_DEVICE|                |   TYPE_MEMORY_DEVICE |    |    | |   (ObjectClass)        |   |
       +---------------------+                |class              ---|----+    | |   type             ----|---+
                                              |    (ObjectClass*)    |         | |concrete_class          |
                                              +----------------------+         | |   (ObjectClass*)       |
                                                                               | |interface_type          |
                                                                               | |   (TypeImpl*)          |
                                                                               | +------------------------+
                                                                               |get_addr                  |
                                                                               |set_addr                  |
                                                                               |...                       |
                                                                               |                          |
                                                                               +--------------------------+
```

## 接口类型附属于设备类型

接口类型是一个很有意思的类型，刚才我们看到了TYPE\_MEMORY\_DEVICE会对应有一个MemoryDeviceClass。

对于普通的设备类型，那整个系统中就只会有这么一个对应的Class，但是接口类型则不是。

还是从代码上来看：

```
static void type_initialize(TypeImpl *ti)
{
  ...
  for (i = 0; i < ti->num_interfaces; i++) {
    TypeImpl *t = type_get_by_name(ti->interfaces[i].typename);
    for (e = ti->class->interfaces; e; e = e->next) {
        TypeImpl *target_type = OBJECT_CLASS(e->data)->type;

        if (type_is_ancestor(target_type, t)) {
            break;
        }
    }

    if (e) {
        continue;
    }

    type_initialize_interface(ti, t, t);
  }
  ...
}
```

对于定义了interfaces成员的类型，在初始化中将通过type\_initialize\_interface来创建自己的接口类型。 而这个类型不仅在系统中注册，还会添加到class->interfaces链表上。

```
                                              +----------------------------------------------------------------+-----+
                                              |                                                                |     |
                                              |                                MemoryDeviceClass               |     |
                                              v                                +--------------------------+    |     |
                                              TypeImpl*                        |InterfaceClass            |    |     |
                                              +----------------------+    +--> | +------------------------+    |     |
                                              |name                  |    |    | |parent_class            |    |     |
                                              |   TYPE_MEMORY_DEVICE |    |    | |   (ObjectClass)        |    |     |
                                              |class              ---|----+    | |   type             ----|----+     |
                                              |    (ObjectClass*)    |         | |interface_type          |          |
                                              +----------------------+         | |   (TypeImpl*)          |          |
                                                         ^                     | |concrete_class          |          |
                                                         |                     | |   (ObjectClass*)       |          |
                                                         |                     | +------------------------+          |
                                                         |                     |get_addr                  |          |
                                                         |                     |set_addr                  |          |
                                                         |                     |...                       |          |
                                                         |                     |                          |          |
                                                         |                     +--------------------------+          |
                                                         |                                                           |
                                                         |                                                           |
                                                         |                                                           |
    TypeImpl                                 +----------------------------------------------------------------+      |
    +--------------------------+             |           |                                                    |      |
    |name                      |             |           |                    MemoryDeviceClass               |      |
    |   TYPE_PC_DIMM           |             v           |                    +--------------------------+    |      |
    +--------------------------+             TypeImpl*   |                    |InterfaceClass            |    |      |
               ^                             +----------------------+    +--> | +------------------------+    |      |
               |                             |name                  |    |    | |parent_class            |    |      |
    PCDIMMDeviceClass                        |   TYPE_PC_DIMM::     |    |    | |   (ObjectClass)        |    |      |
    +--------------------------+             |   TYPE_MEMORY_DEVICE |    |    | |   type             ----|----+      |
    |parent_class              |      +----->|class              ---|----+    | |interface_type      ----|-----------+
    |   (ObjectClass)          |      |      |    (ObjectClass*)    |         | |   (TypeImpl*)          |
    |      interfaces      ----|------+      +----------------------+         | |concrete_class      ----|----+
    |                          |                                              | |   (ObjectClass*)       |    |
    +--------------------------+                                              | +------------------------+    |
    ^                                                                         |get_addr                  |    |
    |                                                                         |set_addr                  |    |
    |                                                                         |...                       |    |
    |                                                                         |                          |    |
    |                                                                         +--------------------------+    |
    |                                                                                                         |
    |                                                                                                         |
    +---------------------------------------------------------------------------------------------------------+
```

希望这个图能够对理解接口有一点点帮助。

## 设置接口类型的“虚函数”

接口类型重要的成员就是它的虚函数了，那谁在什么时候设置呢？

因为接口类型是从属于设备类型的，所以虚函数的设置在设备类型初始化函数中设置。

对于pc-dimm设备，这个函数就是pc\_dimm\_class\_init中了。

```
    DeviceClass *dc = DEVICE_CLASS(oc);
    PCDIMMDeviceClass *ddc = PC_DIMM_CLASS(oc);
    MemoryDeviceClass mdc = MEMORY_DEVICE_CLASS(oc);
    mdc->get_addr = pc_dimm_md_get_addr;
    mdc->set_addr = pc_dimm_md_set_addr;
```

## 从设备类型到接口类型

在上面这段代码中有一个有意思的地方就是怎么从设备类型PC\_DIMM\_CLASS转换到接口类型MEMORY\_DEVICE\_CLASS的

让我们来看一眼：

```
#define MEMORY_DEVICE_CLASS(klass) \
     OBJECT_CLASS_CHECK(MemoryDeviceClass, (klass), TYPE_MEMORY_DEVICE)

#define OBJECT_CLASS_CHECK(class_type, class, name) \
        ((class_type *)object_class_dynamic_cast_assert(OBJECT_CLASS(class), (name), \
                                          __FILE__, __LINE__, __func__))
```

经过这两个宏，最后会落到函数object\_class\_dynamic\_cast()。

而这个函数就是沿着klass->interfaces链表查找名字为TYPE\_MEMORY\_DEVICE的类型。如果找到了唯一的，那就范围它。

怎么样，现在是不是能看清楚这个函数的意义，以及设备类到接口类的转换了？
