これは InterSystems FAQ サイトの記事です。
PythonからObjectScriptのルーチンを直接呼び出すことはできませんが、クラスメソッドを経由して間接的に呼び出すことができます。
しかし、Pythonの変数とObjectScriptのローカル変数は内部構造が異なるため、情報の交換には少し工夫が必要です。
簡単なサンプルでその方法について説明します。
まず、2つの変数を足し算する簡単なルーチン ^testを作ります。
TEST
set sum = a + b
次にこの^testを呼び出すPythonのメソッドを含んだUser.testというクラスを作ります。
そしてpyという名前のPythonのメソッドを作成します。
先述の通りPythonからObjectScriptのルーチンを直接呼び出すことはできないので、ルーチンを間接的に呼び出すObjectScriptのメソッドを作成する必要があり、そのメソッドをPythonメソッドから呼び出すようにします。
渡したいデータが複数個ある場合、その数分引数を用意するのは面倒なため、Pythonの場合、情報をまとめて交換する際にdictionary(辞書)やlistという構造を使用することができます。
ここでは、dictionaryを使用する例を紹介します。
ClassMethod py() [ Language = python ]
{
import iris
rtn = "^test"
arg = {"a":10, "b":20}
ret = iris.cls('User.test').callrtn(rtn, arg)
print (ret.get("sum"))
}
次にルーチンを呼び出すためのクラスメソッドを定義します。
PythonのDictionary構造をObjectScriptで操作するためには、少し特別な処理が必要です。
ClassMethod callrtn(rtnname As %String, plist As %String) As %Integer [ ProcedureBlock = 0 ]
{
set a = plist."get"("a")
set b = plist."get"("b")
do @rtnname
kill rtnname,plist
set ret = ##class(%SYS.Python).Builtins().dict()
for {
set %=$Order(@%)
quit:%=""
continue:%="ret"
do ret.setdefault(%, @%)
}
quit ret
}
2023.2以降のバージョンではarrayrefのサポートが追加されており、より直感的な処理が可能になりました。
ClassMethod py() [ Language = python ]
{
import iris
rtn = "^test"
arg = {"a":10, "b":20}
ar = iris.arrayref(arg)
ret = iris.cls('Test.pytest').callrtn(rtn,ar)
print (ret.get("sum"))
}
ClassMethod callrtn(rtnname As %String, plist As %String) As %Integer [ ProcedureBlock = 0 ]
{
set a = plist("a")
set b = plist("b")
do @rtnname
kill rtnname, plist
set ret = ##class(%SYS.Python).Builtins().dict()
set % = "%"
for {
set %=$order(@%)
quit:%=""
continue:%="ret"
do ret.setdefault(%, @%)
}
quit ret
}