When building a solution, the NK compiler uses the EDL, CDL and IDL descriptions to generate a set of special methods and types that simplify the creation, forwarding, receipt and processing of IPC messages.
Let us look at the static description of the server
entity from the echo example. This description consists of three files: server.edl
, ping.cdl
and ping.idl
:
server.edl
/* Server entity description */
entity server
/* ping_comp – named instance of the ping component. */
ping_comp: ping
ping.cdl
/* Ping component description */
component ping
/* ping_impl – an implementation of the IPing interface declared in the ping package. */
ping_impl: ping.IPing
ping.idl
/* Ping package description */
package ping
interface IPing {
Ping(in UInt32 value, out UInt32 result);
}
These files will be used to generate the files named server.edl.h
, server.edl.c
, ping.cdl.h
, ping.cdl.c
, ping.idl.h
and ping.idl.c
, which contain the following methods and types:
Methods and types that are common to the client and server
In our example, one abstract interface will be generated – IPing
:
struct IPing_ops {
nk_err_t (*Ping)(struct IPing *,
const struct IPing_req *,
const struct nk_arena *,
struct IPing_res *,
struct nk_arena *); };
struct IPing {
const struct IPing_ops *ops;
};
When calling an interface method, corresponding values of the RIID and MID are automatically inserted into the request, after which the nk_transport_call()
function is called.
In our example, a single IPing_Ping
interface method will be generated:
nk_err_t IPing_Ping(struct IPing *,
const struct IPing_Ping_req *,
const struct nk_arena *,
struct IPing_Ping_res *,
struct nk_arena *);
Methods and types used only on the client
A proxy object is used as an argument in an interface method. In our example, a single IPing_proxy
proxy object type will be generated:
struct IPing_proxy {
struct IPing base;
struct nk_transport *transport;
nk_iid_t iid;
};
In our example, the single initializing function IPing_proxy_init
will be generated:
void IPing_proxy_init(struct IPing_proxy *, struct nk_transport *, nk_iid_t);
In our example, two such types will be generated: IPing_Ping_req
(for a request) and IPing_Ping_res
(for a response).
struct IPing_Ping_req {
struct nk_message base_;
nk_uint32_t value;
};
struct IPing_Ping_res {
struct nk_message base_;
nk_uint32_t result;
};
Methods and types used only on the server
In our example, the ping_component
structure and ping_component_init
function will be generated:
struct ping_component {
struct IPing *ping_impl;
};
void ping_component_init(struct ping_component *, struct IPing *);
In our example, the server_entity
structure and server_entity_init
function will be generated:
struct server_entity {
struct ping_component *ping_comp;
};
void server_entity_init(struct server_entity *, struct ping_component *);
The dispatcher analyzes the RIID and MID values contained in the request and calls the implementation of the corresponding method.
If a message does not match the interface (for example, if it is for another interface or component), the dispatcher returns NK_EOK
or NK_ENOENT
.
In our example, three dispatchers will be generated: IPing_dispatch
, ping_component_dispatch
and server_entity_dispatch
:
nk_err_t IPing_dispatch(struct IPing *,
const struct nk_message *,
const struct nk_arena *,
struct nk_message *,
struct nk_arena *);
nk_err_t ping_component_dispatch(struct ping_component *,
const struct nk_message *,
const struct nk_arena *,
struct nk_message *,
struct nk_arena *);
nk_err_t server_entity_dispatch(struct server_entity *,
const struct nk_message *,
const struct nk_arena *,
struct nk_message *,
struct nk_arena *);
In our example, two such types will be generated: IPing_req
(for a request) and IPing_res
(for a response).
union IPing_req {
struct nk_message base_;
struct IPing_Ping_req Ping;
};
union IPing_res {
struct nk_message base_;
struct IPing_Ping_res Ping;
};
In our example, two such types will be generated: ping_component_req
(for a request) and ping_component_res
(for a response).
union ping_component_req {
struct nk_message base_;
union IPing_req ping_impl;
};
union ping_component_res {
struct nk_message base_;
union IPing_res ping_impl;
};
In our example, two such types will be generated: server_entity_req
(for a request) and server_entity_res
(for a response).
union server_entity_req {
struct nk_message base_;
union IPing_req ping_comp_ping_impl;
};
union server_entity_res {
struct nk_message base_;
union IPing_res ping_comp_ping_impl;
};