13. Структура передается как последовательность полей. rpcgen также создает определение типа для данного имени переменной (typedef).
14. Размеченное объединение состоит из целочисленного дискриминанта и набора типов данных (ветвей), зависящих от значения дискриминанта. В табл. 16.2 мы показываем, что дискриминант должен быть типа int, но он может быть и unsigned int, и enum, и bool (все эти типы передаются как 32-разрядные целые). При передаче размеченного объединения передается 32-разрядное значение дискриминанта, за которым следует значение той ветви, которая ему соответствует. В ветви default часто объявляется тип void, что означает отсутствие передаваемой вслед за дискриминантом информации. Ниже мы продемонстрируем это на примере.
15. Дополнительные данные представляют собой специальный тип объединения, описанный в примере из листинга 16.24. Объявление XDR выглядит как объявление указателя в языке С, и именно указатель объявляется в созданном заголовочном файле.
На рис. 16.3 сведена информация о кодировании различных типов данных в XDR.
Рис. 16.3. Кодирование типов данных в XDR
Пример: использование XDR без RPC
Приведем пример использования XDR без RPC. Мы воспользуемся стандартом XDR для кодирования структуры данных в машинно-независимое представление, в котором они могут быть обработаны другими системами. Этот метод может использоваться для написания файлов или для отправки данных по сети в машинно-независимом формате. В листинге 16.11 приведен текст файла спецификации data .х, который на самом деле является файлом спецификации XDR, поскольку мы не объявляем никаких процедур RPC.
ПРИМЕЧАНИЕ
Суффикс имени файла (.х) происходит от термина «файл спецификации XDR». Спецификация RPC утверждает, что язык RPC (RPCL) идентичен XDR в части, относящейся к описанию данных. В RPCL была добавлена только возможность описания процедур.
//sunrpc/xdr1/data.x
1 enum result_t {
2 RESULT_INT = 1, RESULT_DOUBLE = 2
3 };
4 union union_arg switch (result_t result) {
5 case RESULT_INT:
6 int intval;
7 case RESULT_DOUBLE:
8 double doubleval;
9 default:
10 void;
11 };
12 struct data {
13 short short_arg;
14 long long_arg;
15 string vstring_arg128; /* строка переменной длины */
16 opaque fopaque_arg[3]; /* скрытые данные фиксированной длины */
17 opaque vopaque_arg; /* скрытые данные переменной длины */
18 short fshort_arg[4]; /* массив фиксированной длины */
19 long vlong_arg; /* массив переменной длины */
20 union_arg uarg;
21 };
1-11 Мы объявляем перечислимый тип с двумя значениями и размеченное объединение, использующее это перечисление в качестве дискриминанта. Если дискриминант имеет значение RESULT_INT, после значения дискриминанта передается целое число. Если дискриминант имеет значение RESULT_DOUBLE, за ним передается число с плавающей точкой двойной точности. В противном случае после дискриминанта не передается ничего.
12-21 Мы объявляем структуру, состоящую из различных типов, поддерживаемых XDR.
Поскольку мы не объявляем процедур RPC, программа rpcgen не создаст заглушку клиента и заглушку сервера. Однако она создаст заголовочный файл data.h и файл data_xdr.с, содержащий функции XDR, обеспечивающие кодирование и декодирование данных, объявленных в файле data.х.
В листинге 16.12 приведен получающийся в результате работы rpcgen заголовочный файл data.h. Содержимое этого файла выглядит так, как мы и предполагали (табл. 16.2).
//sunrpc/xdr1/data.h
1 /*
2 * Please do not edit this file. It was generated using rpcgen.
3 */
4 #ifndef _DATA_H_RPCGEN
5 #define _DATA_H_RPCGEN
6 #include rpc/rpc.h
7 enum result_t {
8 RESULT_INT = 1,
9 RESULT_DOUBLE = 2
10 };
11 typedef enum result_t result_t;
12 struct union_arg {