導入
メインフレーム上の開発において、PL/Iで記述されたメインプログラムから、C言語で書かれた資産やライブラリを呼び出すケースは少なくありません。この際、最も頭を悩ませるのが「文字列の表現形式」の違いです。PL/Iの標準的な文字列と、C言語のヌル終端文字列の間には壁があります。この課題をスマートに解決し、記述子の変換という煩雑な処理を不要にするのがVARYINGZ属性です。
基礎知識
通常、PL/IのVARYING属性は、文字列の長さを先頭の2バイトに格納する「長さ+データ」形式をとります。これに対し、C言語の文字列は、データの末尾にヌル文字(’00’X)を配置することで文字列の終わりを判別する「ヌル終端」形式です。
VARYINGZ属性は、PL/Iの変数でありながら、内部的にC言語のルールである「末尾のヌル文字」を自動的に管理します。これにより、C言語側のサブルーチンに対して、文字列のポインタをそのまま渡すことが可能になります。
実装/解決策
VARYINGZ属性を使用する際は、宣言時に最大長を指定するだけで、それ以外の特別なロジックは不要です。コンパイラが自動的にヌル文字の付与・管理を行ってくれるため、プログラマは文字列の長さを気にすることなく、C言語の関数へ安全にデータを引き渡せます。
サンプルプログラム
以下は、VARYINGZ属性を用いて、C言語側で実装された関数(例:文字列の長さを表示するC関数)を呼び出すイメージのコードです。
/ PL/I側: VARYINGZ属性を使用した宣言 /
DCL C_MESSAGE CHAR(50) VARYINGZ;
/ C言語側の関数定義(イメージ): void print_len(char s) /
DCL PRINT_LEN ENTRY EXTERNAL OPTIONS(ASM, LINKAGE(C));
/ 処理開始 /
C_MESSAGE = ‘Hello, Mainframe!’;
/ VARYINGZにより、末尾に’00’Xが自動付与されている /
/ C言語関数へポインタ渡しを行う /
CALL PRINT_LEN(C_MESSAGE);
/
解説:
C_MESSAGEに値を代入すると、コンパイラが自動的に
‘Hello, Mainframe!’ + ’00’X の形式にメモリを整えます。
そのため、C言語側は通常の char として受け取るだけで処理が可能です。
/
応用・注意点
VARYINGZを使用する際、最も注意すべきは「最大長」の概念です。宣言したサイズ(この場合は50)には、ヌル文字分が含まれている必要があります。もしギリギリの長さを扱う場合、C言語側でバッファオーバーフローを引き起こさないよう、PL/I側で定義する最大長には余裕を持たせる設計が推奨されます。
また、既存のPL/IロジックでVARYINGZを適用する場合、既存の文字列操作関数が正しく動作するか(ヌル文字を含めてカウントしてしまう可能性があるか)を事前に検証してください。C言語連携が必須の環境であれば、この属性を活用することで、変換用の中間バッファを削減し、コードの保守性を劇的に向上させることができます。

コメント