Руководство программиста в Photon (1037671), страница 59
Текст из файла (страница 59)
int, long, short, (signed или unsigned).
Например, unsigned int my_scalar.
Tr_ENDIAN_ARRAY( typedef_name, member ) - Массив из short или int элементов.
Например, short short_nums[10].
Tr_ENDIAN_REF( typedef_name, member, num ) - Ссылка на эндиан-скаляры. Например, int *nums.
Имея для нашего простого типа данных задание эндиан-списка, давайте создадим определение, чтобы обратиться в транспортный реестр:
static const PhTransportRegEntry_t Simp1TransDef = {
"simp1",
Ph_PACK_STRUCT,
sizeof( Simp1_t ),
0,
NULL,
&Simp1Endians,
NULL
};
Структура PhTransportRegEntry_t включает следующие члены:
char*type | Имя регистрируемого типа |
int unsigned packing | Метод установки, который будет использоваться (один из: Ph_PACK_RAW, Ph_PACK_STRING или Ph_PACK_STRUCT) |
int unsigned size | Размер типа данных в байтах |
int unsigned num_fixups | Количество элементов в массиве fixups |
PhTransportFixupRec_t const *fixups | Список инструкций по работе со ссылками на данные, определённые вне типа. Подробнее будет обсуждено далее |
int unsigned const *endians | Завершающийся нулём массив эндиан-информации, описанный выше |
int unsigned const *clear_refs | Завершающийся нулём массив членов, которые должны быть очищены (т.е. установлены в NULL), когда данные этого типа распакованы |
Чтобы зарегистрировать этот впервые определённый тип, вызовите функцию PhRegisterTransportType():
PhRegisterTransportType(&Simp1, TransDef);
Этот новый тип Simp1 может теперь использоваться с любой функцией транспортировки при упаковке или распаковке данных.
Приложению-адресату нет нужды беспокоиться об эндиан-ориентации источника. Когда адресат распаковывает данные этого типа, транспортный механизм автоматически корректирует эндиан-ориентацию, используя эндиан-определение в зарегистрированном транспортном типе. Это весьма выгодно в мультиплатформенном сетевом окружении. Если транспортный механизм используется для записи двоичных конфигурационных файлов, одни и те же файлы могут использоваться приложениями независимо от эндиан-ориентации машин, на которых они выполняются.
Более сложная структура
Вам часто надо транспортировать данные более сложных типов, которые ссылаются на внешние по отношению к себе данные (члены типа указателей). При выполнении операций упаковки и распаковки такие члены требуют специальную обработку. Для того, чтобы эти члены были обработаны надлежащим образом, они должны быть описаны в члене fixup элемента транспортного реестра.
Вот более сложная структура:
typedef struct simp2 {
/* Скаляр и ссылка на скалярный массив */
int num_ref_vals;
int *ref_vals;
/* Скалярный массив */
int nums_10[10];
/* Скалярный массив (не эндиан-чувствительный) */
char first_name[10];
/* ССылка на строку */
char *last_name2;
/* Скалярный массив */
short vals_5[5];
/* Член зарегистрированного типа */
Simp1_t simp1_instance;
/* Массив членов зарегистрированного типа */
Simp1_t simp1_array[4];
/* Ссылка на зарегистрированный тип */
Simp1_t *simp1_reference;
/* Скаляр и ссылка на массив зарегистрированных типов */
int num_simps;
Simp1_t *ref_simp1_array;
/* Скаляр и ссылка на массив ссылок зарегистрированных типов */
int num_simp_refs;
Simp1_t **ref_simp1_ref_array;
/* Два скаляра и ссылка на данные произвольного объёма */
short bm_height;
int bm_bpl;
char *bitmap;
/* Нечто, что мы не хотим паковать, но хотим очистить после распаковки */
char *dont_pack_this;
} Simp2_t;
Список ссылок на очистку
Вот список clear_refs для этой структуры:
static const int unsigned Simp2ClearRefs[] = {
offsetof( Simp2_t, dont_pack_this ),
0 /* Конец списка ссылок на очистку */
};
Эндиан-список
Вот эндиан-список для этой структуры:
static const int unsigned Simp2Endians[] = {
Tr_ENDIAN( Simp2_t, num_ref_vals ),
Tr_ENDIAN_REF( Simp2_t, ref_vals ),
Tr_ENDIAN_ARRAY( Simp2_t, nums_10 ),
Tr_ENDIAN_ARRAY( Simp2_t, vals_5 ),
0 /* Конец эндиан-списка */
};
Вот полный список эндиан-декларации для каждого типа членов:
Скаляр (char) | Отсутствует |
Скаляр (short) | Tr_ENDIAN( type, member ) |
Скаляр (int) | Tr_ENDIAN( type, member ) |
Скалярный массив (char) | Отсутствует |
Скалярный массив (short) | Tr_ENDIAN_ARRAY( type, member ) |
Скалярный массив (int) | Tr_ENDIAN_ARRAY( type, member ) |
Ссылка (char) | Отсутствует |
Ссылка (short) | Tr_ENDIAN_REF( type, member ) |
Ссылка (int) | Tr_ENDIAN_REF( type, member ) |
Ссылка (массив char) | Отсутствует |
Ссылка (массив short) | Tr_ENDIAN_REF( type, member ) |
Ссылка (массив int) | Tr_ENDIAN_REF( type, member ) |
Простая структура | Список каждого эндиан-чувствительного члена структуры членов |
Зарегистрированный тип | Отсутствует |
Ссылка на зарегистрированный тип | Отсутствует |
Например, для структуры Sample_t:
int i; | Tr_ENDIAN( Sample_t, i ) |
int array[7]; | Tr_ENDIAN_ARRAY( Sample_t, array ) |
short *short_nums; | Tr_ENDIAN_REF( Sample_t, short_nums ) |
int *long_nums; | Tr_ENDIAN_REF( Sample_t, long_nums ) |
struct my_simp ms; | Tr_ENDIAN( Sample_t, ms.width ), Tr_ENDIAN( Sample_t, ms.height ) |
Fixup-список
Структура Simp2_t, приведенная выше, включает несколько членов, ссылающихся на данные вне этой структуры. Эти элементы требуют наличия членов типа PhTransportFixupRec_t в списке fixup, чтобы указать транспортному механизму, как получить данные:
static const PhTransportFixupRec_t
Simp2Fixups[] = {
Tr_REF_ARRAY( Simp2_t, ref_vals, Tr_FETCH( Simp2_t, num_ref_vals ) ),
Tr_STRING( Simp2_t, name2 ),
Tr_TYPE( Simp2_t, simp1_instance ),
Tr_TYPE_ARRAY( Simp2_t, simp1_array ),
Tr_REF_TYPE( Simp2_t, simp1_reference ),
Tr_REF_TYPE_ARRAY(
Simp2_t, ref_simp1_array,
Tr_FETCH( Simp2_t, num_simps ) ),
Tr_REF_TYPE_REF_ARRAY(
Simp2_t, ref_simp1_ref_array,
Tr_FETCH( Simp2_t, num_simp_refs ) ),
Tr_ALLOC(
Simp2_t, bitmap,
Tr_FETCH( Simp2_t, bm_bpl ), '*',
Tr_FETCH( Simp2_t, bm_height ) )
};
При определении элемента в fixup Вам может понадобиться использовать информацию, находящуюся в структуре, элемент которой Вы определяете. В этой ситуации используйте декларацию:
Tr_FETCH(type, member) | Эта декларация приводит к тому, что значение задаваемого члена будет использоваться во время исполнения – когда данные будут паковаться или распаковываться. Кроме того, любые члены, определённые через другие зарегистрированные типы, автоматически являются эндиан-корректными, используя эндиан-определение из элемента транспортного реестра. |
Вот полный список деклараций адресной привязки:
Scalar | Скаляр. Отсутствует |
Scalar Array | Массив скаляров. Отсутствует |
Reference (string) | Сссылка (строка). Tr_STRING (type, member) |
Reference (scalar array) | Ссылка (массив скаляров). Tr_REF_ARRAY (type, member, number_of_elements) |
Registered type | Зарегистрированный тип. Tr_TYPE (type, member, type_name) |
Registered type array | Массив зарегистрированных типов. Tr_TYPE_ARRAY(type, member, type_name) |
Reference (registered type) | Ссылка (зарегистрированный тип). Tr_REF_TYPE (type, member, type_name) |
Reference (registered type array) | Ссылка (массив зарегистрированных типов). Tr_REF_TYPE_ARRAY (type, member, num_elements, type_name) |
Reference (registered type reference array) | Ссылка (массив ссылок на зарегистрированные типы). Tr_REF_TYPEREF_ARRAY (type, member, num_elements, type_name) |
Вот несколько примеров членов и их деклараций адресной привязки:
char *name;
Tr_STRING( Sample_t, name )
int num_nums;
int *int_array;
Tr_REF_ARRAY( Sample_t, int_array, Tr_FETCH( Sample_t, num_nums) )
или, если член известен:
Tr_REF_ARRAY( Sample_t, int_array, 7 )
Simp1_t simple_instance
Tr_TYPE( Sample_t, simple_instance, "simp1" )
или как один экземпляр, если это просто массив:
Tr_TYPE_ARRAY( Sample_t, simple_instance, "simp1" )
Simp1_t simple_array[5]
Tr_TYPE_ARRAY( Sample_t, simple_array, "simp1" )
Simp1_t *simp1_ref
Tr_REF_TYPE( Sample_t, simp1_ref, "simp1" )
short num_simp1s;
Simp1_t *simp1_ref
Tr_REF_TYPE_ARRAY( Sample_t, simp1_ref, Tr_FETCH( Sample_t, num_simp1s ), "simp1" )
short num_simp1s;
Simp1_t **simp1_ref;
Tr_REF_TYPE_REF_ARRAY( Sample_t, simp1_ref,
Tr_FETCH( Sample_t, num_simp1s ), "simp1" )
Элемент реестра
Наконец, вот элемент реестра для Simp2_t:
static const PhTransportRegEntry_t
Simp2TransDef = {
"simp2",
Ph_PACK_STRUCT,
sizeof( Simp2_t ),
sizeof(Simp2Fixups)/sizeof(Simp2Fixups[0]),
&Simp2Fixups,
&Simp2Endians,
&Simp2ClearRefs
};
Транспортные функции
В этом разделе описываются низкоуровневые функции и типы данных, относящиеся к механизму транспортировки. Некоторые функции вызываются приложением, которое является источником данных. Некоторые функции вызываются приложением, которое является источником данных, некоторые – адресатом, некоторые – и тем и другим.
Оба приложения
Оба приложения используют:
PhTransportRegEntry_t | Структура данных, описывающая транспортируемые данные |
PhRegisterTransportType() | Добавляет новый транспортный тип в реестр транспортировки |
PhFindTransportType() | Отыскивает транспортный тип в реестре транспортировки |
Приложение-источник
Приложение-источник использует это, примерно в таком порядке:
PhTransportCtrl_t | Структура управления для механизма транспортировки Photon'а |
PhCreateTransportCtrl() | Выделяет память под структуру PhCreateTransportCtrl() |
PhTransportType() | Упаковывает данные в структуру PhTransportCtrl_t |
PhTransportFindLink() | Отыскивает связанный список данных транспортировки для некоторых специфических данных |
PhTransportLink_t | Элемент связанного списка транспортных данных |
PhLinkTransportData() | Добавляет транспортные данные в связанный список |
PhGetNextInlineData() | Получает данные из следующего элемента связанного списка транспортных данных |
PhGetTransportVectors() | Строит вектор ввода/вывода транспортируемых данных |
PhFreeTransportType() | Освобождает данные, связанные с элементом транспортного реестра |
PhReleaseTransportCtrl() | Освобождает структуру PhTransportCtrl_t |
Это низкоуровневые функции, которые Вам, вероятно, никогда не понадобятся вызывать непосредственно:
PhAllocPackType() | Выделяет буфер и упаковывает в него транспортные данные |
PhPackEntry() | Упаковывает транспортные данные, установленные элементом транспортного реестра |
PhPackType() | Упаковывает транспортные данные, установленные типом данных |
Приложение-адресат
Приложение-адресат использует следующее, примерно в таком порядке:
PhGetAllTransportHdrs() | Извлекает все заголовки из буфера упакованных транспортных данных |
PhGetTransportHdr() | Извлекает заголовок из буфера упакованных транспортных данных |
PhGetNextTransportHdr() | Получает следующий заголовок из буфера упакованных транспортных данных |
PhLocateTransHdr() | Ищет специфические данные в связанном списке транспортных заголовков |
PhMallocUnpack() | Распаковывает транспортные данные, используя самостоятельно написанную функцию выделения памяти |
PhUnpack() | Распаковывает транспортные данные |
PhUnlinkTransportHdr() | Удаляет элемент из связанного списка транспортных заголовков |
PhReleaseTransportHdrs() | Освобождает связанный список заголовков упакованных транспортных данных |
Глава 22. Регионы
В Photon'е все приложения состоят из одного или более прямоугольников, называемых регионами (regions), находящихся в неком абстрактном трёхмерном пространстве событий. Регионам назначены идентификационные номера типа PhRid_t.
В этой главе обсуждается:
-
Координатное пространство Photon'а
-
Координаты региона
-
Регионы и отсечение событий
-
Месторасположение и иерархия
-
Использование регионов
-
Системная информация
Вы можете использовать утилиту phview, чтобы посмотреть, какие регионы существуют на Вашей машине. Для более подробной информации см. "Справочник утилит".
Координатное пространство Photon'а
Координатное пространство Photon'а выглядит так: