Skip to main content

外部言語の操作

$system.external インタフェースにより、対応する Java、.NET、または Python のターゲット・オブジェクトを制御する ObjectScript プロキシ・オブジェクトを生成できます。プロキシ・オブジェクトにはターゲットと同じメソッドとプロパティのセットがあり、プロキシの呼び出しがそれぞれターゲットによりエコーされます。プロキシとターゲット間の通信は、Java、.NET、または Python の External Server に接続された ObjectScript Gateway オブジェクトにより管理されます。

ゲートウェイ・オブジェクトと InterSystems 外部サーバ間の接続
接続図 : プロキシ・オブジェクト <-> ゲートウェイ・オブジェクト <-> TCP/IP <-> 外部サーバ <-> ターゲット・オブジェクト
  • ゲートウェイ・プロセスは、InterSystems IRIS ネームスペース内で実行され、ObjectScript アプリケーションの接続を管理します。

  • InterSystems 外部サーバ・プロセスは、外部言語環境 (Java、.NET、または Python) で実行され、外部言語共有ライブラリへのインタフェースを提供します。個々のサーバ・スレッドは、クラスのメソッドとプロパティへのアクセスを提供し、プロキシとターゲット・オブジェクト間の通信を管理します。

  • 双方向のTCP/IP 接続により、ゲートウェイ・オブジェクトと外部サーバは、外部サーバ・インスタンスを一意に識別するポート番号を使用してメッセージを交換できるようになります。

以下のセクションでは、接続を確立し、ターゲットを定義し、プロキシ・オブジェクトを使用する方法を説明します。

ゲートウェイの作成とプロキシ・オブジェクトの使用

接続の開始、プロキシ・オブジェクトの作成、およびメソッドの呼び出しのプロセス全体を、1 つの文に圧縮できます。以下の例は Java 外部サーバを開始し、ターゲット・クラス java.util.Date のインスタンスのプロキシを作成し、日付を表示するメソッドを呼び出します。

  write $system.external.getJavaGateway().new("java.util.Date").toString()

     Sun May 02 15:18:15 EDT 2021

この 1 行のコードは、プロキシ・オブジェクトの作成と使用のプロセス全体を示します。Java ゲートウェイ接続を確立し、クラス java.util.Date のインスタンスと対応する ObjectScript プロキシを作成し、メソッド toString() から返された日付を書きこみます。

Tip:

InterSystems ターミナルでこの呼び出しを実行してみましょう。C# と Python での同等のコマンドを以下に示します。

    write $system.external.getDotNetGateway.new("System.DateTime",0).Now
    write $system.external.getPythonGateway.new("datetime.datetime",1,1,1).now().strftime(%c)

外部サーバは InterSystems IRIS のインストール時に自動的に設定され、それ以上注意を払わなくてもほぼ確実に動作します (そうでない場合、“外部サーバの定義のトラブルシューティング” を参照してください。希望の言語のプラットフォームを識別するパス設定を変更する必要がある場合があります)。

前の例では、すべてを 1 行に圧縮していましたが、その行は以下の 3 つの重要な動作を実行します。

  • まず、ObjectScript と外部サーバ間の接続をカプセル化する ObjectScript Gateway オブジェクトを作成します。ゲートウェイを永続変数に割り当てることができます。

      set javaGate = $system.external.getJavaGateway()
    
  • 次に、ゲートウェイ・オブジェクトの new() メソッドを呼び出します。これは java.util.Date のインスタンスを外部サーバ・スレッドに作成し、対応するプロキシ・オブジェクトを ObjectScript プロセスに作成します。プロキシ・オブジェクトを永続変数に割り当てることもできます。

      set dateJava = javaGate.new("java.util.Date")
    
  • 最後に、プロキシのオブジェクト・メソッドを呼び出します。ターゲット・オブジェクトは呼び出しをエコーし、結果をプロキシに返します。

      write dateJava.toString()
    

以下の例は、3 つすべての言語でのこれらの手順を示しています。

ゲートウェイ・オブジェクトの作成

Java、.NET、および Python 外部サーバそれぞれに、getJavaGateway()getDotNetGateway()getPythonGateway() の固有のゲートウェイ作成メソッドがあります。これらの各メソッドは既定の構成で外部サーバを開始し、Gateway オブジェクトを返して接続を管理します。

  set javaGate = $system.external.getJavaGateway()
  set netGate = $system.external.getDotNetGateway()
  set pyGate = $system.external.getPythonGateway()

また、カスタマイズされた外部サーバ構成で使用するための汎用の getGateway() メソッドもありますが (詳細は “外部サーバの定義のカスタマイズ” を参照)、ほとんどの目的には既定のメソッドで十分なはずです。

プロキシ・オブジェクトの作成

各ゲートウェイ・オブジェクトには、ターゲット・オブジェクトとプロキシ・オブジェクトを作成するための new() メソッドがあります。new() メソッドへの各呼び出しでは、クラス名と必要なすべての引数を指定します。呼び出しを実行すると、外部サーバはクラスのターゲット・インスタンスを作成し、ゲートウェイはターゲットと同じメソッドとプロパティのセットを持つ対応するプロキシ・オブジェクトを作成します。プロキシへの各呼び出しはターゲットによってエコーされ、結果がプロキシに返されます。

この例では、3 つの異なる外部サーバ (各言語に独自のサーバが必要であるため) を介して接続される 3 つのプロキシ・オブジェクトを作成します。

  set dateJava = javaGate.new("java.util.Date")
  set dateNet = newGate.new("System.DateTime",0)
  set datePy = pyGate.new("datetime.datetime",1,1,1).now()

各プロキシは、その他の ObjectScript オブジェクトと同様に扱うことができます。3 つすべてを、同じ ObjectScript アプリケーションで使用できます。

プロキシ・オブジェクトのメソッドとプロパティの呼び出し

同じ文で、3 つすべてのプロキシ・オブジェクトからのメソッド呼び出しとプロパティ呼び出しを使用できます。

  write !,"  Java: "_dateJava.toString(),!,"  .NET: "_dateNet.Now,!, "Python: "_datePy.strftime("%c")
       Java: Sun May 02 15:18:15 EDT 2021
       .NET: 2021-05-02 16:38:36.9512565
     Python: Sun May 02 15:23:55 2021

Java および Python の例はメソッドの呼び出しで、.NET の例ではプロパティを使用しています。

これまでの例では、システム・クラスのみを使用していました。これらはいつでも利用可能なので、説明しやすいためです。その他の場合は、使用する前にクラスの場所を指定する必要があります。詳細は、後述する “ターゲット・ソフトウェアへのパスの定義” を参照してください。

ターゲット・ソフトウェアへのパスの定義

すべての Gateway オブジェクトには、特定言語のソフトウェア・ライブラリへのパスのリストを格納できます。Jave ゲートウェイは .jar ファイルを受け入れ、.NET ゲートウェイは .dll アセンブリを受け入れ、Python ゲートウェイは .py (モジュールまたはクラス) ファイルを受け入れます。

addToPath() メソッドでは、リストへの新しいパスを追加できます。path 引数は 1 つのパスを含む単純な文字列にするか、複数のパスを含む動的配列にすることができます。以下に例を示します。

単一パスの追加
  do javaGate.addToPath("/home/myhome/someclasses.jar")
  do netGate.addToPath("C:\Dev\myApp\somedll.dll")
  do pyGate.addToPath("/rootpath/person.py")

Java ゲートウェイと .NET ゲートウェイは、1 つ以上の共有ライブラリを含むフォルダへのパスも受け入れます。高度な Python オプションの詳細は、“Python のターゲットの指定” を参照してください。

動的配列へのパスの追加

%DynamicArrayOpens in a new tab クラスは、JSON 配列構造を簡単に作成できるようにする ObjectScript ラッパです。動的配列の %Push() メソッドを使用して、配列にパスの文字列を追加します。以下の例は、配列 pathlist に 2 つのパスを追加し、それを Java Gateway オブジェクトの addToPath() メソッドに渡します。

  set pathlist = []
  do pathlist.%Push("/home/myhome/firstpath.jar")
  do pathlist.%Push("/home/myhome/another.jar")
  do javaGate.addToPath(pathlist)

動的配列の詳細は、"JSON の使用" の “動的配列での %Push と %Pop の使用” を参照してください。

Note:

path 引数は、複数のパス文字列を含む %Library.ListOfDataTypesOpens in a new tab のインスタンスとしても指定できますが、使いやすさを考慮すると動的配列をお勧めします。

以下の例は、各言語にクラスを指定する方法を示しています。

Java クラスへのパスの定義

Java の場合、パスにはフォルダまたは jar を指定できます。以下の例は、someclasses.jar へのパスを追加し、次に someclasses.classname のインスタンスのプロキシを作成します。

  set javaGate = getJavaGateway()
  do javaGate.addToPath("/home/myhome/someclasses.jar")
  set someProxy = javaGate.new("someclasses.classname")
.NET クラスへのパスの定義

.NET の場合、パスにはフォルダまたはアセンブリを指定できます。以下の例は、someassembly.dll へのパスを追加し、次に someassembly.classname のインスタンスのプロキシを作成します。

  set netGate = getDotNetGateway()
  do netGate.addToPath("C:\Dev\myApp\somedll.dll")
  set someProxy = netGate.new("someassembly.classname")
Python クラスへのパスの定義

Python の場合、パスにはモジュールまたはパッケージを指定できます。モジュールがパッケージの一部である場合、モジュールのパスはパッケージの最上位のディレクトリから開始するドット表記で指定する必要があります。例えば、モジュール Foo.py へのパスは、以下の 2 つの方法のどちらかで指定できます。

  • モジュールとして処理される場合の標準のパス表記 : C:\Dev\demo\Foo.py

  • パッケージ demo の一部として処理される場合のドット表記 : C:\Dev\demo.Foo.py

以下の例は、動的配列を使用して、フォルダ C:\Dev\demo\ に含まれる 2 つの異なるファイルへのパスを追加します。ファイル Foo.py には、パッケージ化されていないクラス personOne が含まれ、ファイル Bar.py には、パッケージ demo の一部であるクラス personTwo が含まれます。new() を呼び出すと、以下のように両方のクラスのプロキシが作成されます。

  set pyPaths = []
  do pyPaths.%Push("C:\Dev\demo\Foo.py")
  do pyPaths.%Push("C:\Dev\demo.Bar.py")

  set pyGate = getPythonGateway()
  do pyGate.addToPath(pyPaths)
  set fooProxy = pyGate.new("Foo.personOne")
  set barProxy = pyGate.new("demo.Bar.personTwo")

動的配列の詳細は、"JSON の使用" の “動的配列での %Push と %Pop の使用” を参照してください。

クラスのないモジュールまたはパッケージのターゲットを割り当てることも可能です (以降のセクションを参照)。

Python のターゲットの指定

Python のターゲットを指定する構文は、ターゲットがパッケージまたはクラスのいずれに含まれるか、その両方か、またはどちらでもないかによって異なります。以下の例は、パスが addToPath() で指定され、クラス名が new() で指定される場合を示しています。

クラスの例では、person がメイン・クラスで、company はそれがインポートするクラスです。インポートされるクラスは、それが別個のファイル内にあるとしても、指定する必要はありません。

クラスのないモジュールまたはパッケージのターゲットも割り当てられますが、それらは実質的に静的なメソッドおよびプロパティに制限されます (クラスなしでクラス・インスタンス・メソッドを持つことはできないため)。

パッケージなし、クラスなし

パッケージもクラスもないモジュールは、ファイル名を使用します。new() の引数は、ファイル名の後にピリオドが続き、クラスがないことを示していることに注意してください。

  do pyGate.addToPath("/rootpath/noclass.py")
  set proxy = pyGate.new("noclass."))

パッケージなし、1 つのファイル内に 2 つのクラス

メイン・クラス person およびインポートされるクラス company は両方ともファイル /rootpath/onefile.py 内にあります。

  do pyGate.addToPath(/rootpath/onefile.py")
  set proxy = pyGate.new("onefile.person")
パッケージなし、別個のファイル内に 2 つのクラス

メイン・クラス person およびインポートされるクラス company は、/rootpath 内の別個のファイルに含まれます。

  do pyGate.addToPath(/rootpath/person.py")
  set proxy = pyGate.new("person.person")
パッケージ、クラスなし

クラスなしのパッケージでは、パッケージ名とファイル名を使用します。この例でのファイルの実際のパスは /rootpath/demo/noclass.py になります。new() の引数はピリオドで終了し、クラスがないことを示しています。

  do pyGate.addToPath(/rootpath/demo.noclass.py")
  set proxy = pyGate.new("demo.noclass.")
パッケージ、1 つのファイル内に 2 つのクラス

メイン・クラス person およびインポートされるクラス company は両方ともファイル /rootpath/demo/onefile.py 内にあります:

  do pyGate.addToPath(/rootpath/demo.onefile.py")
  set proxy = pyGate.new("demo.onefile.person")
パッケージ、別個のファイル内に 2 つのクラス

メイン・クラス person およびインポートされるクラス company は、/rootpath/demo 内の別個のファイルに含まれます。

  do pyGate.addToPath(/rootpath/demo.person.py")
  set proxy = pyGate.new("demo.person.person")
FeedbackOpens in a new tab