The transmit_as Attribute

The transmit_as attribute offers a way to control data marshalling without worrying about marshalling data at a low level — that is, without worrying about data sizes or byte swapping in a heterogeneous environment. By lettting you reduce the amount of data transmitted over the network, the transmit_as attribute can make your application more efficient.

You use the transmit_as attribute to specify a data type that will be used for transmission instead of using the data type provided. You supply routines that convert the data type to and from the type that is used for transmission. You must also supply routines to free the memory used for the data type and the transmitted type. For example, the following defines xmit_type as the transmitted data type for an application-presented type specified as type_spec:

typedef [transmit_as (xmit_type)] type_spec type;
 

The following table describes the four user-supplied routine names. Type is the data type known to the application, and xmit_type is the data type used for transmission:

Routine Description
type_to_xmit Allocates an object of the transmitted type and converts from presented type to transmitted type (caller and callee).
type_from_xmit Converts from transmitted type to presented type (caller and callee).
type_free_inst Frees resources used by the presented type (callee only).
type_free_xmit Frees storage returned by the type_to_xmit routine (caller and callee).

Other than by these four user-supplied functions, the transmitted type is not manipulated by the application. The transmitted type is defined only to move data over the network. After the data is converted to the type used by the application, the memory used by the transmitted type is freed.

These user-supplied routines are provided by either the client or the server application based on the directional attributes.

If the parameter is in only, the client transmits to the server. The client needs the type_to_xmit and type_free_xmit functions. The server needs the type_from_xmit and type_free_inst functions.

For an out-only parameter, the server transmits to the client. The server needs the type_to_xmit and type_free_xmit functions, while the client needs the type_from_xmit function.

For the temporary xmit_type objects, the stub will call type_free_xmit to free any memory allocated by a call to type_to_xmit.

Certain guidelines apply to the presented type instance. If the presented type is a pointer or contains a pointer, then the type_from_xmit routine must allocate pointees of the pointers (the presented type object itself is manipulated by the stub in the usual way).

For out and in, out parameters, or one of their components, of a type that contains the transmit_as attribute, the type_free_inst routine is automatically called for the data objects that have the attribute. For in parameters, the type_free_inst routine is called only if the transmit_as attribute has been applied to the parameter. If the attribute has been applied to the components of the parameter, the type_free_inst routine is not called. There are no freeing calls for the embedded data and at-most-one call (related to the top-level attribute) for an in only parameter.

Effective with MIDL version 2.0, both client and server must supply all four functions. For example, a linked list can be transmitted as a sized array. The type_to_xmit routine walks the linked list and copies the ordered data into an array. The array elements are ordered so the many pointers associated with the list data structure do not have to be transmitted. The type_from_xmit routine reads the array and puts its elements into a linked-list data structure.

The double-linked list (DOUBLE_LINK_LIST) includes data and pointers to the previous and next list elements:

typedef struct _DOUBLE_LINK_LIST {
    short sNumber;
    struct _DOUBLE_LINK_LIST * pNext;
    struct _DOUBLE_LINK_LIST * pPrevious;
} DOUBLE_LINK_LIST;
 

Rather than shipping the complex data structure, the transmit_as attribute can be used to send it over the network as an array. The sequence of items in the array retains the ordering of the elements in the list at a lower cost:

typedef struct _DOUBLE_XMIT_TYPE {
    short sSize;
    [size_is(sSize)] short asNumber[];
} DOUBLE_XMIT_TYPE;
 

The transmit_as attribute appears in the IDL file:

typedef [transmit_as(DOUBLE_XMIT_TYPE)]  DOUBLE_LINK_LIST
                                         DOUBLE_LINK_TYPE;
 

In the following example, ModifyListProc defines the parameter of type DOUBLE_LINK_TYPE as an in, out parameter:

void ModifyListProc([in, out] DOUBLE_LINK_TYPE * pHead)
 

The four user-defined functions use the name of the type in the function names and use the presented and transmitted types as parameter types, as required:

void __RPC_USER DOUBLE_LINK_TYPE_to_xmit ( 
     DOUBLE_LINK_TYPE __RPC_FAR * pList, 
     DOUBLE_XMIT_TYPE __RPC_FAR * __RPC_FAR * ppArray);

void __RPC_USER DOUBLE_LINK_TYPE_from_xmit ( 
     DOUBLE_XMIT_TYPE __RPC_FAR * pArray,
     DOUBLE_LINK_TYPE __RPC_FAR * pList);

void __RPC_USER DOUBLE_LINK_TYPE_free_inst ( 
     DOUBLE_LINK_TYPE __RPC_FAR * pList);

void __RPC_USER DOUBLE_LINK_TYPE_free_xmit ( 
     DOUBLE_XMIT_TYPE __RPC_FAR * pArray);