Сгенерированные методы и типы
При сборке решения компилятор NK на основе EDL-, CDL- и IDL-описаний генерирует набор специальных методов и типов, упрощающих формирование, отправку, прием и обработку IPC-сообщений.
Рассмотрим статическое описание сущности Server
из примера echo. Это описание состоит из трех файлов: Server.edl
, Ping.cdl
и Ping.idl
:
Server.edl
/* Описание сущности Server. */
entity Server
/* pingComp - именованный экземпляр компонента Ping. */
components {
pingComp: Ping
}
Ping.cdl
/* Описание компонента Ping. */
component Ping
/* pingImpl - реализация интерфейса Ping. */
interfaces {
pingImpl: Ping
}
Ping.idl
/* Описание интерфейса Ping. */
package Ping
interface {
Ping(in UInt32 value, out UInt32 result);
}
На основе этих файлов будут сгенерированы файлы Server.edl.h
, Ping.cdl.h
, и Ping.idl.h
содержащие следующие методы и типы:
Методы и типы, общие для клиента и сервера
- Абстрактные интерфейсы, содержащие указатели на реализации входящих в них методов.
В нашем примере будет сгенерирован один абстрактный интерфейс –
Ping
:struct Ping_ops {
nk_err_t (*Ping)(struct Ping *,
const struct Ping_req *,
const struct nk_arena *,
struct Ping_res *,
struct nk_arena *); };
struct Ping {
const struct Ping_ops *ops;
};
- Набор интерфейсных методов.
При вызове интерфейсного метода в запросе автоматически проставляются соответствующие значения RIID и MID, после чего вызывается функция
nk_transport_call()
.В нашем примере будет сгенерирован единственный интерфейсный метод
Ping_Ping
:nk_err_t Ping_Ping(struct Ping *,
const struct Ping_Ping_req *,
const struct nk_arena *,
struct Ping_Ping_res *,
struct nk_arena *);
Методы и типы, используемые только на клиенте
- Типы прокси-объектов.
Прокси-объект используется как аргумент интерфейсного метода. В нашем примере будет сгенерирован единственный тип прокси-объекта
Ping_proxy
:struct Ping_proxy {
struct Ping base;
struct nk_transport *transport;
nk_iid_t iid;
};
- Функции для инициализации прокси-объектов.
В нашем примере будет сгенерирована единственная инициализирующая функция
Ping_proxy_init
:void Ping_proxy_init(struct Ping_proxy *, struct nk_transport *, nk_iid_t);
- Типы, определяющие структуру фиксированной части сообщения для каждого конкретного метода.
В нашем примере будет сгенерировано два таких типа:
Ping_Ping_req
(для запроса) иPing_Ping_res
(для ответа).struct Ping_Ping_req {
struct nk_message base_;
nk_uint32_t value;
};
struct Ping_Ping_res {
struct nk_message base_;
nk_uint32_t result;
};
Методы и типы, используемые только на сервере
- Тип, содержащий реализации всех интерфейсов компонента, а также инициализирующая функция. (Для каждого компонента сервера.)
При наличии вложенных компонентов этот тип также содержит их экземпляры, а инициализирующая функция принимает соответствующие им инициализированные структуры. Таким образом, при наличии вложенных компонентов, их инициализацию необходимо начинать с самого вложенного.
В нашем примере будет сгенерирована структура
Ping_component
и функцияPing_component_init
:struct Ping_component {
struct Ping *pingImpl;
};
void Ping_component_init(struct Ping_component *, struct Ping *);
- Тип, содержащий реализации всех интерфейсов предоставляемых сущностью-сервером непосредственно; все экземпляры компонентов, входящие в сущность-сервер; а также инициализирующая функция.
В нашем примере будет сгенерирована структура
Server_entity
и функцияServer_entity_init
:struct Server_entity {
struct Ping_component *pingComp;
};
void Server_entity_init(struct Server_entity *, struct Ping_component *);
- Типы, определяющие структуру фиксированной части сообщения для любого метода конкретного интерфейса.
В нашем примере будет сгенерировано два таких типа:
Ping_req
(для запроса) иPing_res
(для ответа).union Ping_req {
struct nk_message base_;
struct Ping_Ping_req Ping;
};
union Ping_res {
struct nk_message base_;
struct Ping_Ping_res Ping;
};
- Типы, определяющие структуру фиксированной части сообщения для любого метода любого интерфейса, реализация которого включена в конкретный компонент.
При наличии вложенных компонентов эти типы также содержат структуры фиксированной части сообщения для любых методов любых интерфейсов, реализации которых включены во все вложенные компоненты.
В нашем примере будет сгенерировано два таких типа:
Ping_component_req
(для запроса) иPing_component_res
(для ответа).union Ping_component_req {
struct nk_message base_;
union Ping_req pingImpl;
};
union Ping_component_res {
struct nk_message base_;
union Ping_res pingImpl;
};
- Типы, определяющие структуру фиксированной части сообщения для любого метода любого интерфейса, реализация которого включена в любой компонент, экземпляр которого входит в серверную сущность.
При наличии вложенных компонентов эти типы также содержат структуры фиксированной части сообщения для любых методов любых интерфейсов, реализации которых включены во все вложенные компоненты.
В нашем примере будет сгенерировано два таких типа:
Server_entity_req
(для запроса) иServer_entity_res
(для ответа).union Server_entity_req {
struct nk_message base_;
union Ping_req pingComp_pingImpl;
};
union Server_entity_res {
struct nk_message base_;
union Ping_res pingComp_pingImpl;
};
- Dispatch-методы (диспетчеры) для отдельного интерфейса, компонента или сущности.
Диспетчеры анализируют полученный запрос (значения RIID и MID), вызывают реализацию соответствующего метода, после чего сохраняют ответ в буфер. В нашем примере будут сгенерированы диспетчеры
Ping_dispatch
,Ping_component_dispatch
иServer_entity_dispatch
.Диспетчер сущности обрабатывает запрос и вызывает методы, реализуемые этой сущностью. Если запрос содержит некорректный RIID (например, относящийся к другой реализации интерфейса, которой нет у этой сущности) или некорректный MID, диспетчер возвращает
NK_EOK
илиNK_ENOENT
.nk_err_t Server_entity_dispatch(struct Server_entity *,
const union Server_entity_req *,
const struct nk_arena *,
union Server_entity_res *,
struct nk_arena *);
В специальных случаях можно использовать диспетчеры интерфейса и компонента. Они принимают дополнительный аргумент – ID реализации интерфейса (
nk_iid_t
). Запрос будет обработан только если переданный аргумент и RIID из запроса совпадают, а MID корректен. В противном случае диспетчеры возвращаютNK_EOK
илиNK_ENOENT
.nk_err_t Ping_dispatch(struct Ping *,
nk_iid_t,
const union Ping_req *,
const struct nk_arena *,
union Ping_res *,
struct nk_arena *);
nk_err_t Ping_component_dispatch(struct Ping_component *,
nk_iid_t,
const union Ping_component_req *,
const struct nk_arena *,
union Ping_component_res *,
struct nk_arena *);