11.3. Использование Kobj

11.3.1. Структуры

    struct kobj_method

11.3.2. Функции

    void kobj_class_compile(kobj_class_t cls);
    void kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops);
    void kobj_class_free(kobj_class_t cls);
    kobj_t kobj_create(kobj_class_t cls, struct malloc_type *mtype, int mflags);
    void kobj_init(kobj_t obj, kobj_class_t cls);
    void kobj_delete(kobj_t obj, struct malloc_type *mtype);

11.3.3. Макросы

    KOBJ_CLASS_FIELDS
    KOBJ_FIELDS
    DEFINE_CLASS(name, methods, size)
    KOBJMETHOD(NAME, FUNC)

11.3.4. Объявления функция

    <sys/param.h>
    <sys/kobj.h>

11.3.5. Создание шаблона интерфейса

Первый шаг при использовании Kobj заключается в создании интерфейса. Создание интерфейса включает создание шаблона, который может использоваться скриптом src/sys/kern/makeobjops.pl для генерации файла объявлений и кода для объявлений метода и функций поиска методов.

Внутри этого шаблона используются следующие ключевые слова: #include, INTERFACE, CODE, METHOD, STATICMETHOD и DEFAULT.

Директива #include и то, что следует далее, без изменений копируется в начало файла генерируемого кода.

Например:

    #include <sys/foo.h>

Ключевое слово INTERFACE используется для определения имени интерфейса. Это имя объединяется с именем каждого метода в виде [имя интерфейса]_[имя метода]. Он имеет синтаксис INTERFACE [имя интерфейса];.

Например:

    INTERFACE foo;

Ключевое слово CODE копирует свои аргументы без изменений в файл кода. Он имеет синтаксис CODE { [нечто] };

Например:

    CODE {
        struct foo * foo_alloc_null(struct bar *)
        {
            return NULL;
    }
    };

Ключевое слово METHOD описывает метод. Его синтаксис METHOD [возвращаемый тип] [имя метода] { [объект [, аргументы]] };

For example:

    METHOD int bar {
        struct object *;
        struct foo *;
        struct bar;
    };

Ключевое слово DEFAULT может следовать за ключевым словом METHOD. Оно расширяет ключевое слово METHOD добавлением к методу функции, используемой по умолчанию. Расширенный синтаксис имеет вид METHOD [возвращаемый тип] [имя метода] { [объект; [другие аргументы]] }DEFAULT [функция по умолчанию];

Например:

    METHOD int bar {
        struct object *;
        struct foo *;
        int bar;
    } DEFAULT foo_hack;

Ключевое слово STATICMETHOD используется так же, как и METHOD, за исключением того, что данные kobj не располагаются в начале структуры обхекта, поэтому приведение к типу kobj_t будет некорректным. Вместо этого STATICMETHOD опирается на данные Kobj, на которые ссылаются как 'ops'. Это также полезно для непосредственного вызова методов из таблицы методов класса.

Другие законченные примеры:

    src/sys/kern/bus_if.m
    src/sys/kern/device_if.m

11.3.6. Создание класса

Второй шаг при использовании Kobj заключается в создании класса. Класс состоит из имени, таблицы методов и размера объектов, если использовались механизмы обработки объекта Kobj. Для создания класса воспользуйтесь макросом DEFINE_CLASS(). Для создания таблицы методов создайте массив из kobj_method_t, завершающийся NULL. Каждый элемент, не равный NULL, может быть создан при помощи макроса KOBJMETHOD().

Например:

    DEFINE_CLASS(fooclass, foomethods, sizeof(struct foodata));
    
    kobj_method_t foomethods[] = {
        KOBJMETHOD(bar_doo, foo_doo),
        KOBJMETHOD(bar_foo, foo_foo),
        { NULL, NULL}
    };

Класс должен быть "откомпилирован". В зависимости от состояния системы в момент, когда класс инициализирует статически выделяемый кэш, используется "таблица ops". Это может быть достигнуто объявлением struct kobj_ops и использованием kobj_class_compile_static();, в противном случае должна быть использована функция kobj_class_compile().

11.3.7. Создание объекта

Третий шаг в использовании Kobj включает и то, как определить объект. Процедуры создания объекта Kobj предполагают, что данные Kobj располагаются в начале объекта. Если это не подходит, то вам нужно распределить оюхект самостоятельно и затем воспользоваться функцией kobj_init() над его частью, относящейся к Kobj; в противном случае вы можете использовать функцию kobj_create() для выделения и инициализации части Kobk объекта автоматически. kobj_init() можно также использовать для изменения класса, который использует объект.

Для интеграции Kobj в объект, вы должны использовать макрос KOBJ_FIELDS.

Например

    struct foo_data {
        KOBJ_FIELDS;
        foo_foo;
        foo_bar;
    };

11.3.8. Вызов методов

Последний шаг в использовании Kobj сводится просто к использованию сгенерированных функция для вызова требуемого метода из класса объекта. Это также просто, как использование имени интерфейса и имени метода с некоторыми модификациями. Имя интерфейса должно быть объединено с именем метода через символ '_' между ними, все в верхнем регистре.

К примеру, если имя интерфейса было foo, а метод назывался bar, то вызов будет таким:

    [return value = ] FOO_BAR(object [, other parameters]);

11.3.9. Очистка

Когда объект, распределенный через kobj_create(), больше не нужен, то над ним может быть выполнена функция kobj_delete(), а когда класс больше не используется, то над ним может быть выполнен вызов kobj_class_free().