The represent_as Attribute

The [ represent_as] attribute lets you specify how a particular transmittable data type is represented to the application. This is done by specifying the name of the represented type for a known transmittable type and supplying the conversion routines. You must also supply the routines to free the memory used by the data type objects.

Use the [represent_as] attribute to present an application with a different, possibly untransmittable, data type rather than the type that is actually transmitted between the client and server. It is also possible that the type the application manipulates can be unknown at the time of MIDL compilation. When you choose a well-defined transmittable type, you need not be concerned about data representation in the heterogeneous environment. The [represent_as] attribute can make your application more efficient by reducing the amount of data transmitted over the network.

The [represent_as] attribute is similar to the [ transmit_as] attribute. However, while [transmit_as] lets you specify a data type that will be used for transmission, [represent_as] lets you specify how a data type is represented for the application. The represented type need not be defined in the MIDL processed files; it can be defined at the time the stubs are compiled with the C compiler. To do this, use the include directive in the application configuration file (ACF) to compile the appropriate header file. For example, the following ACF defines a type local to the application, repr_type, for the transmittable type named_type:

typedef [represent_as(repr_type) [, type_attribute_list] named_type;

The following table describes the four programmer-supplied routines.

Routine Description
named_type_from_local Allocates an instance of the network type and converts from the local type to the network type.
named_type_to_local Converts from the network type to the local type.
named_type_free_local Frees memory allocated by a call to the named_type_to_local routine, but not the type itself.
named_type_free_inst Frees storage for the network type (both sides).

 

Other than by these four programmer-supplied routines, the named type is not manipulated by the application. The only type visible to the application is the represented type. The application uses the represented type name instead of the transmitted type name in the prototypes and stubs generated by the compiler. You must supply the set of routines for both sides.

For temporary named_type objects, the stub will call named_type_free_inst to free any memory allocated by a call to named_type_from_local.

If the represented type is a pointer or contains a pointer, the named_type_to_local routine must allocate memory for the data to which the pointers point (the represented type object itself is manipulated by the stub in the usual way). For [ out] and [ in, out] parameters of a type that contain [represent_as or one of its components, the named_type_free_local routine is automatically called for the data objects that contain the attribute. For [in] parameters, the named_type_free_local routine is called only if the [represent_as] attribute has been applied to the parameter. If the attribute has been applied to the components of the parameter, the *_free_local routine is not called. Freeing routines are not called for the embedded data and at-most-once call (related to the top-level attribute) for an [in] only parameter.

Note

It is possible to apply both the [transmit_as] and [represent_as] attributes to the same type. When marshaling data, the [represent_as] type conversion is applied first and then the [transmit_as] conversion is applied. The order is reversed when unmarshaling data. Thus, when marshaling, *_from_local allocates an instance of a named type and translates it from a local type object to the temporary named type object. This object is the presented type object used for the *_to_xmit routine. The *_to_xmit routine then allocates a transmitted type object and translates it from the presented (named) object to the transmitted object.

 

An array of long integers can be used to represent a linked list. In this way, the application manipulates the list, and the transmission uses an array of long integers when a list of this type is transmitted. You can begin with an array, but using a construct with an open array of long integers is more convenient. The following example shows how to do this.

/* IDL definitions */
 
typedef struct_lbox 
{
    long        data;
    struct_lbox *        pNext;
} LOC_BOX, * PLOC_BOX;
 
/* The definition of the local type visible to the application, 
as shown above, can be omitted in the IDL file. See the include 
in the ACF file. */
 
typedef struct_xmit_lbox 
{
    short        Size;
    [size_is(Size)] long DaraArr[];
} LONGARR;
 
void WireTheList( [in,out] LONGARR * pData );
 
/* ACF definitions */
 
/* If the IDL file does not have a definition for PLOC_BOX, you 
can still ready it for C compilation with the following include 
statement (notice that this is not a C include): 
include "local.h";*/
 
typedef [represent_as(PLOC_BOX)] LONGARR;

Note that the prototypes of the routines that use the LONGARR type are actually displayed in the Stub.h files as PLOC_BOX in place of the LONGARR type. The same is true of the appropriate stubs in the Stub_c.c file.

You must supply the following four functions:

void __RPC_USER
LONGARR_from_local(
    PLOC_BOX __RPC_FAR * pList,
    LONGARR __RPC_FAR * _RPC_FAR * ppDataArr );
 
void __RPC_USER
LONGARR_to_local(
    LONGARR __RPC_FAR * _RPC_FAR * ppDataArr,
    PLOC_BOX __RPC_FAR * pList );
 
void __RPC_USER
LONGARR_free_inst(
    LONGARR __RPC_FAR * pDataArr);
 
void __RPC_USER
LONGARR_free_local(
    PLOC_BOX __RPC_FAR * pList );

The routines shown above do the following:

  • The LONGARR_from_local routine counts the nodes of the list, allocates a LONGARR object with the size sizeof(LONGARR) + Count*sizeof(long), sets the Size field to Count, and copies the data to the DataArr field.
  • The LONGARR_to_local routine creates a list with Size nodes and transfers the array to the appropriate nodes.
  • The LONGARR_free_inst routine frees nothing in this case.
  • The LONGARR_free_local routine frees all the nodes of the list.