Estructuras (RPC)
Hay varias categorías de estructuras, progresivamente más complicadas en lo referente a acciones necesarias para serializar. Comienzan con una estructura simple que se puede copiar en bloque en su totalidad y continúan con una estructura compleja que se tiene que atender campo por campo.
- Estructura simple
- Estructura simple con punteros
- Estructura conforme
- Estructura conforme con punteros
- Estructura variable conforme (con o sin punteros)
- Estructura dura
- Estructura compleja
- Descripción del diseño de miembro de estructura
Nota
En comparación con las categorías de matriz, queda claro que solo se pueden describir estructuras de hasta 64 k de tamaño (el tamaño es para la parte plana de la estructura), es decir, no hay ningún equivalente de matrices SM y LG.
Miembros comunes a las estructuras
alignment
Alineación necesaria del búfer antes de deserializar la estructura. Los valores válidos son 0, 1, 3 y 7 (la alineación real menos 1).
memory_size
Tamaño de la estructura en la memoria en bytes; para las estructuras conformes, este tamaño no incluye el tamaño de la matriz.
offset_to_array_description
Desplazamiento del puntero de cadena de formato actual a la descripción de la matriz conforme contenida en una estructura.
member_layout
Descripción de cada elemento de la estructura. Las rutinas NDR solo necesitan examinar esta parte de la cadena de formato de un tipo si se necesita la transformación endian o si el tipo es una estructura compleja.
pointer_layout
Vea la sección Diseño del puntero.
Una estructura simple contiene solo tipos de base, matrices fijas y otras estructuras simples. La característica principal de la estructura simple es que se puede copiar en bloque como un todo.
FC_STRUCT alignment<1>
memory_size<2>
member_layout<>
FC_END
Una estructura simple con punteros contiene solo tipos de base, punteros, matrices fijas, estructuras simples y otras estructuras simples con punteros. Dado que el diseño<> solo tendrá que visitarse al realizar una conversión de endianidad, se coloca al final de la descripción.
FC_PSTRUCT alignment<1>
memory_size<2>
pointer_layout<>
member_layout<>
FC_END
Una estructura conforme contiene solo tipos de base, matrices fijas y estructuras simples, y debe contener una cadena conforme o una matriz conforme. Esta matriz podría estar dentro de otra estructura conforme u otra estructura conforme con punteros incrustados en esta estructura.
FC_CSTRUCT alignment<1>
memory_size<2>
offset_to_array_description<2>
member_layout<>
FC_END
Una estructura conforme con punteros contiene solo tipos de base, punteros, matrices fijas, estructuras simples y estructuras simples con punteros, y debe contener una matriz conforme. Esta matriz podría estar dentro de otra estructura conforme u otra estructura conforme con punteros incrustados en esta estructura.
FC_CPSTRUCT alignment<1>
memory_size<2>
offset_to_array_description<2>
pointer_layout<>
member_layout<> FC_END
Una estructura variable conforme contiene solo tipos de base, punteros, matrices fijas, estructuras simples y estructuras simples con punteros, y debe contener una cadena conforme o una matriz variable conforme. Esta cadena o matriz conforme puede estar dentro de otra estructura conforme u otra estructura conforme con punteros incrustados en esta estructura.
FC_CVSTRUCT alignment<1>
memory_size<2>
offset_to_array_description<2>
[pointer_layout<>]
layout<>
FC_END
La estructura dura era un concepto destinado a eliminar penalizaciones pronunciadas relacionadas con el procesamiento de estructuras complejas. Se deriva de una observación de que una estructura compleja normalmente tiene solo una o dos condiciones que impiden la copia en bloques y, por tanto, arruinan su rendimiento en comparación con una estructura simple. Las causas suele ser uniones o campos de enumeración.
Una estructura dura es una estructura que tiene una enumeración 16, un relleno final en la memoria o una unión como último miembro. Estos tres elementos impiden que la estructura se incluya en una de las categorías de estructura anteriores, que disfrutan de una pequeña sobrecarga de interpretación y potencial de optimización máxima, pero no se fuerzan en la categoría de estructura compleja tan costosa.
La enumeración 16 no debe hacer que los tamaños de memoria y conexión de la estructura difieran. La estructura no puede tener ninguna matriz conforme ni ningún puntero (a menos que formen parte de la unión); los únicos miembros permitidos son tipos de base, matrices fijas y estructuras simples.
FC_HARD_STRUCTURE alignment<1>
memory_size<2>
reserved<4>
enum_offset<2>
copy_size<2>
mem_copy_incr<2>
union_description_offset<2>
member_layout<>
FC_END
El campo enum_offset<2> proporciona el desplazamiento desde el principio de la estructura en la memoria a una enumeración 16 (si se incluye); de lo contrario, el campo enum_offset<2> es –1.
El campo copy_size<2> proporciona el número total de bytes de la estructura, que puede copiarse en bloque en el búfer o desde el mismo. Este total no incluye ninguna unión final ni ningún relleno final en la memoria. Este valor también es la cantidad en la que se debe incrementar el puntero del búfer después de la copia.
El campo mem_copy_incr<2> es el número de bytes que el puntero de memoria debe incrementarse después de la copia en bloque antes de controlar cualquier unión final. Al incrementar mediante esta cantidad (no mediante bytes de copy_size<2>), se genera un puntero de memoria adecuado para cualquier unión final.
Una estructura compleja es cualquier estructura que contenga uno o varios campos que impidan que la estructura se copie en bloque o para la que se debe realizar una comprobación adicional durante la serialización o deserialización (por ejemplo, comprobaciones enlazadas en una enumeración). Los siguientes tipos de NDR se incluyen en esta categoría:
- tipos simples: ENUM16, __INT3264 (solo en plataformas de 64 bits), una integral con [intervalo]
- relleno de alineación al final de la estructura
- punteros de interfaz (usan un complejo incrustado)
- punteros omitidos (lo que se relaciona con el atributo [ignore] y el token FC_IGNORE)
- matrices complejas, matrices variables, matrices de cadena
- matrices conformes multidimensionales con al menos una dimensión no fija
- uniones
- elementos definidos con [transmit_as], [represent_as], [wire_marshal], [user_marshal]
- estructuras complejas incrustadas
- relleno al final de la estructura
Una estructura compleja tiene la siguiente descripción de formato:
FC_BOGUS_STRUCT alignment<1>
memory_size<2>
offset_to_conformant_array_description<2>
offset_to_pointer_layout<2>
member_layout<>
FC_END
[pointer_layout<>]
El campo memory_size<2> es el tamaño de la estructura en la memoria, en bytes.
Si la estructura contiene una matriz conforme, el campo offset_to_conformant_array_description<2> proporciona el desplazamiento a la descripción de la matriz conforme; de lo contrario, es cero.
Si la estructura tiene punteros, el campo offset_to_pointer_layout<2> proporciona el desplazamiento del diseño de la estructura que se ha pasado al diseño del puntero; de lo contrario, este campo es cero.
El campo pointer_layout<> de una estructura compleja se controla de forma algo diferente que en el resto de estructuras. El campo pointer_layout<> de una estructura compleja solo contiene descripciones de campos de puntero reales en la propia estructura. Los punteros contenidos en las matrices, uniones o estructuras incrustadas no se describen en el campo pointer_layout<> de la estructura compleja.
Nota
Esto contrasta con otras estructuras, que duplican también la descripción de los punteros contenidos en matrices o estructuras incrustadas en su propio campo pointer_layout<>.
El formato del diseño del puntero de una estructura compleja también es totalmente diferente. Dado que solo contiene descripciones de miembros de puntero reales y se serializa una estructura compleja y un campo deserializado a la vez, el campo pointer_layout<> solo contiene la descripción del puntero de todos los miembros del puntero. No hay ningún campo FC_PP inicial y ninguno de los datos de pointer_layout<> habituales.
La descripción del diseño de una estructura contiene uno o varios de los siguientes caracteres de formato:
Cualquiera de los caracteres de tipo de base, como FC_CHAR, etc.
Directivas de alineación. Hay tres caracteres de formato que especifican la alineación del puntero de memoria: FC_ALIGNM2, FC_ALIGNM4 y FC_ALIGNM8.
Nota
También hay tokens de alineación del búfer, de FC_ALIGNB2 a FC_ALIGNM8; estos no se usan.
Relleno de memoria. Esto se produce solo al final de la descripción de una estructura e indica el número de bytes de relleno en memoria antes de la matriz conforme en la estructura: FC_STRUCTPADn, donde n es el número de bytes de relleno.
Cualquier tipo no base incrustado (tenga en cuenta que, no obstante, nunca se produce una matriz conforme en el diseño de la estructura). Tiene una descripción de 4 bytes,
FC_EMBEDDED_COMPLEX memory_pad<1> offset_to_description<2>,
donde no se garantiza que el desplazamiento esté alineado con 2 bytes.
memory_pad<1> es un relleno necesario en la memoria antes del campo complejo.
offset_to_description<2> es un desplazamiento de tipo relativo al tipo incrustado.
Si es necesario, también puede haber un campo FC_PAD antes de que finalice FC_END para asegurarse de que la cadena de formato se alinee en un límite de 2 bytes después de FC_END.