PythonからRPGプログラムを呼び出す、パート2
「 PythonからRPGプログラムを呼び出す、パート1」では、単一の文字列のパラメーターを入力および出力として渡し、PythonスクリプトからRPGプログラムを呼び出す方法について紹介しました。このシリーズのパート2では、データ構造をRPGプログラムに渡すことで、プロセスをもう少し堅牢なものにしようと思います。
Pythonスクリプトの最初の部分(以下の最初のコード片)では、 itoolkit モジュールをインポートし、それらをローカル名に割り当てます。次に、RPGオブジェクトが置かれている場所にライブラリー リスト項目を追加する最初のコマンドをセット アップします。
from itoolkit import *
from itoolkit.lib.ilibcall import *
itool.add(iCmd('addlible', 'addlible mllib'))
ここまでのコードは、 パート1の記事と同じです。しかし、その次の部分からは、違いが出てきます。ここでは、文字列の入力および出力パラメーターに加えて、データ構造をRPGプログラムに渡すため、以下のように、 iPgm 関数にコードを追加する必要がありました。
itool.add(
iPgm('my_results','Mlr101Tk')
.addParm(iData('InFirstName','10a','Mike'))
.addParm(
iDS('Address')
.addData(iData('Street','25a','123 Main Street'))
.addData(iData('City','25a','Washington Township'))
.addData(iData('State','2a','NJ'))
.addData(iData('Zip','5p0','07676'))
)
.addParm(iData('OutLastName','10a',' '))
.addParm(iData('OutAddress','75a',' '))
)
ここでは、私のプログラム Mlr101Tk の呼び出しを追加し、出力を変数my_resultsに割り当てました。前回の記事ではパラメーターは2つでしたが、この例では4つのパラメーター( addparmによって示されます)があることに注目してください。1つ目と3つ目のパラメーターは同じですが、2つ目と4つ目のパラメーターが追加されました。2つ目のパラメーターはデータ構造 iDSを定義し、これには住所が格納されます。このデータ構造では、通り、市、州、郵便番号のパラメーターを定義しました。各パラメーターのデータ タイプおよび長さは、RPGプログラムが予期しているものと一致する必要があります。また、RPGプログラムで使用されるパラメーターのそれぞれに値を指定しました。4つ目のパラメーターは、RPGプログラムから返され、フォーマットされた住所を格納します。フォーマットされた住所は、渡される、通り、市、州、郵便番号が連結されたものになります。
iLibCall 関数を使用して、ライブラリー リスト項目を追加し、RPGプログラムを呼び出しました。再度、結果を変数mypgm_resultsに割り当てます。
itool.call(itransport)
# results are returned as a dictionary formatted as Json
mypgm_results = itool.dict_out('my_results')
先に進む前に、RPGプログラムが行う処理を見てみましょう。ここでは、Pythonスクリプトに対応するデータ構造を定義します。
dcl-ds AddressDs qualified template;
Street char(25);
City char(25);
State char(2);
Zip packed(5:0);
end-ds;
次のコード片は、RPGプログラムへ渡されるパラメーターを示しています。パラメーターの順序が、Pythonスクリプトで定義されているのと同じであることに注目してください。
// - - - - - - -
// Prototypes (entry parameters)
dcl-pr Mlr101Tk ExtPgm;
inFirstName char(10);
Address likeds(AddressDs);
outLastName char(10);
outAddress char(75);
End-pr;
// - - - - - - -
// Main procedure interface
dcl-pi Mlr101Tk;
inFirstName char(10);
Address likeds(AddressDs);
outLastName char(10);
outAddress char(75);
end-pi;
最初の記事と同様に、プログラムの残りの部分は非常にシンプルです。出力パラメーター outLastNameに Larsenという値を設定し、渡されたAddressデータ構造からの単一の文字列として出力パラメーター outAddress に値を設定します。
If %trim(inFirstName) = 'Mike'; outLastName = 'Larsen'; Else; outLastName = 'Smith'; Endif; // format the address passed in as one string and send it back to the // Python script. outAddress = %trim(Address.Street) + ' ' + %trim(Address.City) + ', ' + %trim(Address.State) + ' ' + %editc(Address.Zip:'X');ここで、SSH端末を起動してPythonスクリプトを実行します。
プログラムからの結果に含まれる情報は、前記事に比べて、少し多くなっています。これでも読み取ることができますが、もっと読みやすく出力しようと思います。以下のように、Pythonスクリプトにコードを追加して、結果のJSONが読みやすく出力されるようにします。また、別の行に、フォーマットされた住所を出力するようにしました。
mypgm_results = itool.dict_out('my_results')
# Pretty Printing JSON string back
print(json.dumps(mypgm_results, indent = 4))
print('\n')
print ("Formatted address from RPG: " + mypgm_results['OutAddress'])
次のスクリーン ショットは、端末に出力された結果を示しています。
PythonとRPGの統合は、 itoolkitを使用することによって非常に容易になりました。itoolkitを使用して他にどのようなことができるか検討してみたいと思っています。