represent_as属性
[ represent_as] 属性を使用すると、特定の送信可能なデータ型をアプリケーションに表示する方法を指定できます。 これを行うには、既知の転送可能な型に対して表される型の名前を指定し、変換ルーチンを指定します。 また、データ型オブジェクトで使用されるメモリを解放するルーチンも指定する必要があります。
[represent_as] 属性を使用して、クライアントとサーバーの間で実際に送信される型ではなく、変換できない可能性がある別のデータ型をアプリケーションに提示します。 また、MIDL コンパイル時にアプリケーションが操作する型が不明になる可能性もあります。 明確に定義された送信可能な種類を選択する場合、異種環境でのデータ表現について心配する必要はありません。 [represent_as] 属性を使用すると、ネットワーク経由で送信されるデータの量を減らすことで、アプリケーションの効率を高めることができます。
[represent_as] 属性は[ transmit_as] 属性に似ています。 ただし、[ transmit_as] では 転送に使用するデータ型を指定できますが 、[represent_as] では 、アプリケーションのデータ型の表現方法を指定できます。 表される型は、MIDL で処理されるファイルで定義する必要はありません。これは、スタブが C コンパイラでコンパイルされる時点で定義できます。 これを行うには、 アプリケーション構成ファイル (ACF) で include ディレクティブを使用して、適切なヘッダー ファイルをコンパイルします。 たとえば、次の ACF では、送信可能な型named_typeに対して、アプリケーションに対してローカルrepr_type型が定義されています。
typedef [represent_as(repr_type) [, type_attribute_list] named_type;
次の表では、プログラマが提供する 4 つのルーチンについて説明します。
ルーチンによって返される値 | 説明 |
---|---|
named_type_from_local | ネットワークの種類のインスタンスを割り当て、ローカル型からネットワークの種類に変換します。 |
named_type_to_local | ネットワークの種類からローカル型に変換します。 |
named_type_free_local | named_type_to_local ルーチンの呼び出しによって割り当てられたメモリを解放しますが、型自体は解放しません。 |
named_type_free_inst | ネットワークの種類 (両側) のストレージを解放します。 |
これら 4 つのプログラマが提供するルーチン以外では、名前付き型はアプリケーションによって操作されません。 アプリケーションに表示される唯一の型は、表される型です。 アプリケーションは、コンパイラによって生成されたプロトタイプとスタブで、送信された型名の代わりに、表現された型名を使用します。 両側のルーチンのセットを指定する必要があります。
一時的 なnamed_type オブジェクトの場合、スタブは named_type_free_inst を呼び出して、 named_type_from_localの呼び出しによって割り当てられたメモリを解放します。
表される型がポインターであるか、ポインターが含まれている場合、 named_type_to_local ルーチンは、ポインターが指すデータにメモリを割り当てる必要があります (表現された型オブジェクト自体は、通常の方法でスタブによって操作されます)。 [represent_asまたはそのコンポーネントの 1 つを含む型の [out] パラメーターと [in, out] パラメーターの場合、属性を含むデータ オブジェクトに対してnamed_type_free_local ルーチンが自動的に呼び出されます。 [入力] パラメーターの場合、named_type_free_local ルーチンは、パラメーターに [represent_as] 属性が適用されている場合にのみ呼び出されます。 属性が パラメーターのコンポーネントに適用されている場合、 *_free_local ルーチンは呼び出されません。 埋め込みデータに対して解放ルーチンは呼び出されず、最大 1 回の呼び出し (最上位レベルの属性に関連) は [in] のみのパラメーターに対して呼び出されます。
注意
[transmit_as] 属性と [represent_as] 属性の両方を同じ型に適用できます。 データをマーシャリングするときに、最初に [represent_as] 型変換が適用され 、[transmit_as] 変換が適用されます。 データのマーシャリングを解除すると、順序が逆になります。 したがって、マーシャリング時に、*_from_local は名前付き型のインスタンスを割り当て、ローカル型オブジェクトから一時的な名前付き型オブジェクトに変換します。 このオブジェクトは、*_to_xmit ルーチンに使用される、提示された型オブジェクトです。 その後、*_to_xmit ルーチンは、転送された型オブジェクトを割り当て、提示された (名前付き) オブジェクトから転送オブジェクトに変換します。
長整数の配列を使用して、リンク リストを表すことができます。 このようにして、アプリケーションはリストを操作し、この型のリストが送信されるときに、送信は長整数の配列を使用します。 配列から始めることができますが、長整数のオープン配列でコンストラクトを使用する方が便利です。 次の例は、その方法を示したものです。
/* 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;
LONGARR 型を使用するルーチンのプロトタイプは、実際には LONGARR 型の代わりに PLOC_BOX として Stub.h ファイルに表示 されることに注意してください。 同じことが、Stub_c.c ファイル内の適切なスタブにも当てはまります。
次の 4 つの関数を指定する必要があります。
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 );
上記のルーチンでは、次の処理を行います。
- LONGARR_from_local ルーチンは、リストのノードをカウントし、sizeof(LONGARR) + Count*sizeof(long) を持つ LONGARR オブジェクトを割り当て、Size フィールドを Count に設定し、データを DataArr フィールドにコピーします。
- LONGARR_to_local ルーチンは、Size ノードを含むリストを作成し、配列を適切なノードに転送します。
- この場合、 LONGARR_free_inst ルーチンは何も解放しません。
- LONGARR_free_local ルーチンは、リストのすべてのノードを解放します。