# 接口

在一些设备类型定义中我们可以看到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的类型。如果找到了唯一的，那就范围它。

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://richardweiyang-2.gitbook.io/understanding_qemu/00-devices/06-interface.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
