例 3–27 では、proc はタイプ rpcproc_t として宣言されていることに注意してください。 正式には、RPC のプログラム、バージョン、手続き、およびポートは、タイプ u_long として宣言されていました。32ビットマシン上では、u_long の量は 4 バイト (int として) で、64 ビットシステム上では u_long の量は 8 バイトになります。RPC のプログラム、バージョン、手続き、およびポートを宣言できる場合には必ず、u_long と long の代わりに Solaris 7 で導入されたデータタイプ rpcprog_t、rpcvers_t、rpc_proc_t、rpcport_t を使用する必要があります。これらの新しいタイプを使用すると、32 ビットシステムとの下位互換性があるからです。つまり、この新しいデータタイプによって、rpcgen を実行するシステムに関係なく、4 バイトの量が保証されます。プログラム、バージョン、および手続きの u_longバージョンを使用する rpcgen プログラムを引き続き実行すると、32 ビットマシンと 64 ビットマシンでは、異なる結果になる場合があります。そのため、これらを該当する新しいデータタイプに置き換えることをお勧めします。実際、可能な限り long と u_long の使用は避けた方が賢明です。
Solaris 7 以降の rpcgen を起動する場合、rpcgen によって作成されたソースファイルには XDR ルーチンが組み込まれていて、このソースファイルは、そのコードを32 ビットマシンと64 ビットマシン上のどちらで実行するかによって、異なるインラインマクロが使用されます。特にIXDR_GETLONG() と IXDR_PUTLONG() の代わりに、IXDR_GET_INT32() と IXDR_PUT_INT32() マクロが使用されます。たとえば、rpcgen ソースファイル foo.x に以下のコードが組み込まれている場合を考えます。この場合生成されるファイル foo_xdr.c ファイルでは、適切なインラインマクロが使用されているかどうか確認されます。
struct foo { char c; int i1; int i2; int i3; long l; short s; }; |
#if defined(_LP64) || defined(_KERNEL) register int *buf; #else register long *buf; #endif . . . #if defined(_LP64) || defined(_KERNEL) IXDR_PUT_INT32(buf, objp->i1); IXDR_PUT_INT32(buf, objp->i2); IXDR_PUT_INT32(buf, objp->i3); IXDR_PUT_INT32(buf, objp->l); IXDR_PUT_SHORT(buf, objp->s); #else IXDR_PUT_LONG(buf, objp->i1); IXDR_PUT_LONG(buf, objp->i2); IXDR_PUT_LONG(buf, objp->i3); IXDR_PUT_LONG(buf, objp->l); IXDR_PUT_SHORT(buf, objp->s); #endif |
このコードにより、buf は int または long のどちらかになるように宣言されますが、これはマシンが 64 ビットであるか、または 32 ビットであるかによって決まるということに注意してください。
現在は、RPC を通じて転送されるデータタイプのサイズは、4 バイトの量 (32 ビット) に制限されています。8 バイトの long は、アプリケーションが 64 ビットのアーキテクチャを最大限に使用できるようにする場合に提供されます。ただし、プログラマは、 int のために long や、x_putlong() などの long を使用する関数の使用は、可能な限り避ける必要があります。上述したように、RPC プログラム、バージョン、手続きおよびポートにはそれぞれ専用のタイプがあります。データ値が INT32_MIN と INT32_MAX の間にない場合、xdr_long() は失敗します。また、IXDR_GET_LONG() や IXDR_PUT_LONG() などのインラインマクロが使用されると、そのデータは切り捨てられます。u_long 変数についても同様です。詳しくは、xdr_long(3NSL) マニュアルページを参照してください。