(57)【要約】クライアント（３００）は、ユーザ関数シンボル名を取得し、テンプレート関数として定義され、かつ、その内部でユーザ関数を実行するラッパ関数へのポインタを、ユーザ関数の引数及び戻り値の型をテンプレート引数として指定することにより、取得し、ラッパ関数へのポインタを用いてラッパ関数のラッパ関数シンボル名を取得する。サーバ（３１０）は、ユーザ関数シンボル名、ユーザ関数の引数に対応するデータ、ラッパ関数シンボル名、及び、ユーザプログラム及びラッパ関数が共有ライブラリとしてコンパイルされた共有ライブラリ化ユーザプログラムをクライアントから取得し、ユーザ関数シンボル名及びユーザ関数の引数に対応するデータを引数として、ラッパ関数へのポインタで特定される、共有ライブラリ化ユーザプログラム内のラッパ関数を実行する。
2011158478.tif 000002
【特許請求の範囲】
【請求項１】
クライアントとサーバとが相互通信するデータ処理システムであって、
前記クライアントは、
ユーザプログラムに含まれるユーザ関数へのポインタが指すオブジェクトのユーザ関数シンボル名を取得するユーザ関数シンボル名取得部と、
テンプレート関数として定義され、かつ、その内部で前記ユーザ関数を実行するラッパ関数へのポインタを、前記ユーザ関数の引数及び戻り値の型をテンプレート引数として指定することにより、取得するラッパ関数ポインタ取得部と、
前記ラッパ関数へのポインタを用いて、前記ラッパ関数のラッパ関数シンボル名を取得するラッパ関数シンボル名取得部と、を有し、
前記サーバは、
前記ユーザ関数シンボル名、前記ユーザ関数の引数に対応するデータ、前記ラッパ関数シンボル名、及び、前記ユーザプログラム及び前記ラッパ関数が共有ライブラリとしてコンパイルされた共有ライブラリ化ユーザプログラムを前記クライアントから取得する通信部と、
前記通信部により取得された前記ラッパ関数シンボル名を用いて前記ラッパ関数へのポインタを取得するラッパ関数ポインタ取得部と、
前記通信部により取得された前記ユーザ関数シンボル名及び前記ユーザ関数の引数に対応するデータを引数として、前記ラッパ関数へのポインタで特定される、前記共有ライブラリ化ユーザプログラム内の前記ラッパ関数を実行するラッパ関数実行部と、
を有するデータ処理システム。
【請求項２】
前記通信部は、前記ユーザ関数の引数に対応するデータとして、シリアライズされた引数データを前記クライアントから取得し、
前記ラッパ関数実行部は、前記ラッパ関数の実行に伴い実行されるユーザ関数ポインタ取得部及びユーザ関数実行部を含み、
前記ユーザ関数ポインタ取得部は、前記通信部により取得された共有ライブラリ化ユーザプログラム及び前記ユーザ関数シンボル名に基づいて、呼び出すべきユーザ関数へのユーザ関数ポインタを取得し、
前記ユーザ関数実行部は、前記通信部で取得されたシリアライズされた引数データから前記ユーザ関数の引数を復元し、前記ユーザ関数ポインタと、当該復元された引数とを用いて、前記ユーザ関数を実行する、
請求項１に記載のデータ処理システム。
【請求項３】
ユーザプログラムに含まれるユーザ関数へのポインタが指すオブジェクトのユーザ関数シンボル名を取得するユーザ関数シンボル名取得部と、
テンプレート関数として定義され、かつ、その内部で前記ユーザ関数を実行するラッパ関数へのポインタを、前記ユーザ関数の引数及び戻り値の型をテンプレート引数として指定することにより、取得するラッパ関数ポインタ取得部と、
前記ラッパ関数へのポインタを用いて、前記ラッパ関数のラッパ関数シンボル名を取得するラッパ関数シンボル名取得部と、
前記ユーザ関数シンボル名、前記ユーザ関数の引数に対応するデータ、前記ラッパ関数シンボル名、及び、前記ユーザプログラム及び前記ラッパ関数が共有ライブラリとしてコンパイルされた共有ライブラリ化ユーザプログラムを他のコンピュータ装置へ送信する通信部と、
を有するコンピュータ装置。
【請求項４】
ユーザプログラム、及び、テンプレート関数として定義され、かつ、その内部で当該ユーザプログラムに含まれるユーザ関数を実行するラッパ関数が、共有ライブラリとしてコンパイルされた共有ライブラリ化ユーザプログラム、ユーザ関数シンボル名、ユーザ関数の引数に対応するデータ、及び、ラッパ関数シンボル名を他のコンピュータ装置から取得する通信部と、
前記通信部により取得された前記ラッパ関数シンボル名を用いて前記ラッパ関数へのポインタを取得するラッパ関数ポインタ取得部と、
前記通信部により取得された前記ユーザ関数シンボル名及び前記ユーザ関数の引数に対応するデータを引数として、前記ラッパ関数へのポインタで特定される、前記共有ライブラリ化ユーザプログラム内の前記ラッパ関数を実行するラッパ関数実行部と、
を有するコンピュータ装置。
【請求項５】
前記通信部は、前記ユーザ関数の引数に対応するデータとして、シリアライズされた引数データを前記他のコンピュータ装置から取得し、
前記ラッパ関数実行部は、前記ラッパ関数が実行されると起動されるユーザ関数ポインタ取得部及びユーザ関数実行部を含み、
前記ユーザ関数ポインタ取得部は、前記通信部により取得された共有ライブラリ化ユーザプログラム及び前記ユーザ関数シンボル名に基づいて、呼び出すべきユーザ関数へのユーザ関数ポインタを取得し、
前記ユーザ関数実行部は、前記通信部で取得されたシリアライズされた引数データから前記ユーザ関数の引数を復元し、前記ユーザ関数ポインタと、当該復元された引数とを用いて、前記ユーザ関数を実行する、
請求項４に記載のコンピュータ装置。
【請求項６】
相互通信するクライアントとサーバとにより実行されるプログラムであって、
前記クライアントに、
ユーザプログラムに含まれるユーザ関数へのポインタが指すオブジェクトのユーザ関数シンボル名を取得するユーザ関数シンボル名取得部と、
テンプレート関数として定義され、かつ、その内部で前記ユーザ関数を実行するラッパ関数へのポインタを、前記ユーザ関数の引数及び戻り値の型をテンプレート引数として指定することにより、取得するラッパ関数ポインタ取得部と、
前記ラッパ関数へのポインタを用いて、前記ラッパ関数のラッパ関数シンボル名を取得するラッパ関数シンボル名取得部と、
を実現させ、
前記サーバに、
前記ユーザ関数シンボル名、前記ユーザ関数の引数に対応するデータ、前記ラッパ関数シンボル名、及び、前記ユーザプログラム及び前記ラッパ関数が共有ライブラリとしてコンパイルされた共有ライブラリ化ユーザプログラムを前記クライアントから取得する通信部と、
前記通信部により取得された前記ラッパ関数シンボル名を用いて前記ラッパ関数へのポインタを取得するラッパ関数ポインタ取得部と、
前記通信部により取得された前記ユーザ関数シンボル名及び前記ユーザ関数の引数に対応するデータを引数として、前記ラッパ関数へのポインタで特定される、前記共有ライブラリ化ユーザプログラム内の前記ラッパ関数を実行するラッパ関数実行部と、
を実現させるプログラム。
【請求項７】
前記サーバで実現される前記通信部は、前記ユーザ関数の引数に対応するデータとして、シリアライズされた引数データを前記クライアントから取得し、
前記サーバで実現される前記ラッパ関数実行部は、前記ラッパ関数が実行されると起動されるユーザ関数ポインタ取得部及びユーザ関数実行部を含み、
前記ユーザ関数ポインタ取得部は、前記通信部により取得された共有ライブラリ化ユーザプログラム及び前記ユーザ関数シンボル名に基づいて、呼び出すべきユーザ関数へのユーザ関数ポインタを取得し、
前記ユーザ関数実行部は、前記通信部で取得されたシリアライズされた引数データから前記ユーザ関数の引数を復元し、前記ユーザ関数ポインタと、当該復元された引数とを用いて、前記ユーザ関数を実行する、
請求項６に記載のプログラム。
【請求項８】
相互通信するクライアントとサーバとにより実行されるデータ処理方法であって、
前記クライアントが、
ユーザプログラムに含まれるユーザ関数へのポインタが指すオブジェクトのユーザ関数シンボル名を取得し、
テンプレート関数として定義され、かつ、その内部で前記ユーザ関数を実行するラッパ関数へのポインタを、前記ユーザ関数の引数及び戻り値の型をテンプレート引数として指定することにより、取得し、
前記ラッパ関数へのポインタを用いて、前記ラッパ関数のラッパ関数シンボル名を取得し、
前記サーバが、
前記ユーザ関数シンボル名、前記ユーザ関数の引数に対応するデータ、前記ラッパ関数シンボル名、及び、前記ユーザプログラム及び前記ラッパ関数が共有ライブラリとしてコンパイルされた共有ライブラリ化ユーザプログラムを前記クライアントから取得し、
前記ラッパ関数シンボル名を用いて前記ラッパ関数へのポインタを取得し、
前記ユーザ関数シンボル名及び前記ユーザ関数の引数に対応するデータを引数として、前記ラッパ関数へのポインタで特定される、前記共有ライブラリ化ユーザプログラム内の前記ラッパ関数を実行する、
データ処理方法。
【請求項９】
前記ユーザ関数の引数に対応するデータは、シリアライズされた引数データであり、
前記ラッパ関数の実行は、
前記共有ライブラリ化ユーザプログラム及び前記ユーザ関数シンボル名に基づいて、呼び出すべきユーザ関数へのユーザ関数ポインタを取得すること、
前記シリアライズされた引数データから前記ユーザ関数の引数を復元すること、
前記ユーザ関数ポインタと、前記復元された引数とを用いて、前記ユーザ関数を実行することを、含む、
請求項８に記載のデータ処理方法。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、複数のコンピュータ装置をネットワークで結合して並列分散処理を実行するデータ処理技術に関する。
【背景技術】
【０００２】
近年、複数のサーバをネットワークで結合し、これら複数のサーバ上でプログラムを並列に実行する、並列分散処理が行われている。【０００３】
このような並列分散処理を行う場合、プログラマが通信処理を直接記述するのは煩雑なことから、遠隔呼出（Remote Procedure Call：ＲＰＣ）が利用される場合がある。ＲＰＣは、ネットワークで結合された別のサーバ上の手続きの呼出を、通常の手続呼出と同様の書き方で実現するものである。【０００４】
これにより、プログラマは煩雑な通信処理を直接記述せず、手続呼出と同様の記述をすることで、ネットワークで結合された別サーバに処理を行わせて並列分散処理を実現したり、データの授受を行ったりすることができる。【０００５】
ＲＰＣシステムの一例が、下記非特許文献１に記載されている。このＲＰＣシステムにおいては、ＲＰＣを介して呼び出される手続きのインタフェースがある特殊な言語で記述される。【０００６】
この言語は、ＩＤＬ（Interactive Data Language：インタフェース記述言語）と呼ばれることがある。ここでＩＤＬに記述される内容は、呼び出される関数の名前や引数の数および型、返り値の型等である。【０００７】
このＩＤＬをＩＤＬコンパイラによってコンパイルすると、クライアントスタブ、サーバスタブと呼ばれるＣで記述されたプログラムが生成される。クライアントスタブ、サーバスタブには手続呼出をネットワークを介した別のサーバで行うための通信などの処理が記述されている。すなわち、サーバ側プログラムとして、ＩＤＬに記述された関数の定義が記述され、当該関数がサーバスタブとリンクされる。【０００８】
そして、このプログラムが予めサーバ側で実行される。クライアント側プログラムとして、ＩＤＬに記述された関数を呼び出すプログラムが記述され、当該関数がクライアントスタブとリンクされる。クライアント側プログラムが実行されると、当該プログラムが、ＩＤＬで記述された関数を呼び出すところでサーバ側に接続し、サーバ側でその関数が実行されるようになる。【０００９】
他の従来のＲＰＣシステムの一例が、下記特許文献１に記載されている。この従来のＲＰＣシステムでは、Ｊａｖａ（登録商標）を対象とし、コンパイル済みのバイトコードを走査することでクライアントスタブ、サーバスタブに相当するプログラムが自動的に作成させる。これにより、ＩＤＬの記述が不要となる。【００１０】
また、下記特許文献２には、クライアントサーバのＲＰＣにおいて、サーバのライブラリメモリに各種ライブラリが予め格納され、クライアントから関数名称引数の情報がサーバに送信され、サーバは、当該情報に対応するライブラリプログラムをメモリから読み出して実行し、結果をクライアントに返す技術が開示されている。
【先行技術文献】
【特許文献】
【００１１】
【特許文献１】特開平１１−０８５５１９号公報
【特許文献２】特開平１１−３３８７０４号公報
【非特許文献】
【００１２】
【非特許文献１】「ＵＮＩＸネットワークプログラミング」Ｗ．リチャード・スティーヴンス著  篠田陽一訳  トッパン、１９９２年７月３０日、ｐｐ．８０９−８２９(ＵＮＩＸは登録商標)
【発明の概要】
【００１３】
上記非特許文献１に記載されたシステムでは、ＲＰＣを利用するためにＩＤＬを記述するのがプログラマにとって負担である。その理由は、ＩＤＬを用いる場合、ＩＤＬというプログラムを記述する言語とは別の言語を習得する必要があるためである。
【００１４】
また、ＲＰＣで呼び出す関数の引数の数や型、返り値の型等を変更した場合、プログラマは、ＩＤＬも変更し、両者の整合性をとる必要がある。さらに、プログラマは、新たな関数をＲＰＣで呼び出したいと思った場合、ＩＤＬを変更しなければならない。
【００１５】
上記特許文献１に記載されたシステムでは、ＩＤＬを記述する負担は無いものの、利用できるプログラミング言語がＪａｖａ(登録商標)等に限られる。その理由は、上記特許文献１に記載されたシステムは、コンパイル済みのバイトコードを走査することで、引数の数や型、返り値の型等のプログラムの情報を得ていると思われるためである。
【００１６】
Ｊａｖａ（登録商標）のような言語のコンパイラが出力するバイトコードは、ネイティブコードまで変換されておらず、多くの情報を含むが、一般にＣやＣ＋＋といったネイティブコードにコンパイルする言語に比べると速度が遅い。したがって、ＣやＣ＋＋といった、ネイティブコードにコンパイルするより高速な言語の場合には、上記特許文献１に記載された手法は利用できない。
【００１７】
上記特許文献２の技術は、ＯＳ（Operating System）レベルでの動作を想定しており、それを実現するためにはＯＳの変更が必要になる。さらに、「関数名称引数」をクライアント側が取得する方法、サーバがそれを受けとって関数を実行する具体的及び詳細な記述が無いため、実現方法が不明確である。
【００１８】
また、既存のシステムは、クライアント側プログラムとサーバ側プログラムとを別々のプログラムとして記述しなければならず、これがプログラマにとって負担となる。その理由は、ＲＰＣが並列分散処理によって速度を向上させるために利用される場合、分散実行処理を実行するプログラムは、１台のマシン上で実行されるプログラム（ＲＰＣを用いないプログラム）と可能な限り近い形態で記述できた方が、それができない場合よりも、プログラマにとっては負担が軽いためである。既存のシステムでは、分散実行する部分をサーバ側プログラムとして別に扱わなければならず、これがプログラマにとっては負担となる。
【００１９】
本発明は、上述のような課題に鑑みてなされたものであり、開発負荷を増加させることなく、様々な型の引数及び返り値を持つ関数を、或るコンピュータ装置からの指示により、他のコンピュータ装置上で実行させるデータ処理技術を提供するものである。
【００２０】
本発明の各態様では、上述した課題を解決するために、それぞれ以下の構成を採用する。
【００２１】
本発明の第１態様は、相互通信可能なクライアントとサーバとを含むデータ処理システムに関する。第１態様に係るデータ処理システムでは、クライアントは、ユーザプログラムに含まれるユーザ関数へのポインタが指すオブジェクトのユーザ関数シンボル名を取得するユーザ関数シンボル名取得部と、テンプレート関数として定義され、かつ、その内部でユーザ関数を実行するラッパ関数へのポインタを、ユーザ関数の引数及び戻り値の型をテンプレート引数として指定することにより、取得するラッパ関数ポインタ取得部と、ラッパ関数へのポインタを用いて、ラッパ関数のラッパ関数シンボル名を取得するラッパ関数シンボル名取得部と、を有し、サーバは、ユーザ関数シンボル名、ユーザ関数の引数に対応するデータ、ラッパ関数シンボル名、及び、ユーザプログラム及びラッパ関数が共有ライブラリとしてコンパイルされた共有ライブラリ化ユーザプログラムをクライアントから取得する通信部と、通信部により取得されたラッパ関数シンボル名を用いてラッパ関数へのポインタを取得するラッパ関数ポインタ取得部と、通信部により取得されたユーザ関数シンボル名及びユーザ関数の引数に対応するデータを引数として、ラッパ関数へのポインタで特定される、共有ライブラリ化ユーザプログラム内のラッパ関数を実行するラッパ関数実行部と、を有する。
【００２２】
本発明の第２態様に係るコンピュータ装置は、ユーザプログラムに含まれるユーザ関数へのポインタが指すオブジェクトのユーザ関数シンボル名を取得するユーザ関数シンボル名取得部と、テンプレート関数として定義され、かつ、その内部でユーザ関数を実行するラッパ関数へのポインタを、ユーザ関数の引数及び戻り値の型をテンプレート引数として指定することにより、取得するラッパ関数ポインタ取得部と、ラッパ関数へのポインタを用いて、ラッパ関数のラッパ関数シンボル名を取得するラッパ関数シンボル名取得部と、ユーザ関数シンボル名、ユーザ関数の引数に対応するデータ、ラッパ関数シンボル名、及び、ユーザプログラム及びラッパ関数が共有ライブラリとしてコンパイルされた共有ライブラリ化ユーザプログラムを他のコンピュータ装置へ送信する通信部と、を有する。
【００２３】
本発明の第３態様に係るコンピュータ装置は、ユーザプログラム、及び、テンプレート関数として定義され、かつ、その内部で当該ユーザプログラムに含まれるユーザ関数を実行するラッパ関数が、共有ライブラリとしてコンパイルされた共有ライブラリ化ユーザプログラム、ユーザ関数シンボル名、ユーザ関数の引数に対応するデータ、及び、ラッパ関数シンボル名を他のコンピュータ装置から取得する通信部と、通信部により取得されたラッパ関数シンボル名を用いてラッパ関数へのポインタを取得するラッパ関数ポインタ取得部と、通信部により取得されたユーザ関数シンボル名及びユーザ関数の引数に対応するデータを引数として、ラッパ関数へのポインタで特定される、共有ライブラリ化ユーザプログラム内のラッパ関数を実行するラッパ関数実行部と、を有する。
【００２４】
本発明の第４態様は、相互通信するクライアントとサーバとにより実行されるプログラムに関する。第４態様に係るプログラムは、クライアントに、ユーザプログラムに含まれるユーザ関数へのポインタが指すオブジェクトのユーザ関数シンボル名を取得するユーザ関数シンボル名取得部と、テンプレート関数として定義され、かつ、その内部でユーザ関数を実行するラッパ関数へのポインタを、ユーザ関数の引数及び戻り値の型をテンプレート引数として指定することにより、取得するラッパ関数ポインタ取得部と、ラッパ関数へのポインタを用いて、ラッパ関数のラッパ関数シンボル名を取得するラッパ関数シンボル名取得部と、を実現させ、サーバに、ユーザ関数シンボル名、ユーザ関数の引数に対応するデータ、ラッパ関数シンボル名、及び、ユーザプログラム及びラッパ関数が共有ライブラリとしてコンパイルされた共有ライブラリ化ユーザプログラムをクライアントから取得する通信部と、通信部により取得されたラッパ関数シンボル名を用いてラッパ関数へのポインタを取得するラッパ関数ポインタ取得部と、通信部により取得されたユーザ関数シンボル名及びユーザ関数の引数に対応するデータを引数として、ラッパ関数へのポインタで特定される、共有ライブラリ化ユーザプログラム内のラッパ関数を実行するラッパ関数実行部と、を実現させる。
【００２５】
本発明の第５態様は、相互通信するクライアントとサーバとにより実行されるデータ処理方法に関する。第５態様に係るデータ処理方法では、クライアントが、ユーザプログラムに含まれるユーザ関数へのポインタが指すオブジェクトのユーザ関数シンボル名を取得し、テンプレート関数として定義され、かつ、その内部でユーザ関数を実行するラッパ関数へのポインタを、ユーザ関数の引数及び戻り値の型をテンプレート引数として指定することにより、取得し、ラッパ関数へのポインタを用いて、ラッパ関数のラッパ関数シンボル名を取得し、サーバが、ユーザ関数シンボル名、ユーザ関数の引数に対応するデータ、ラッパ関数シンボル名、及び、ユーザプログラム及びラッパ関数が共有ライブラリとしてコンパイルされた共有ライブラリ化ユーザプログラムをクライアントから取得し、ラッパ関数シンボル名を用いてラッパ関数へのポインタを取得し、ユーザ関数シンボル名及びユーザ関数の引数に対応するデータを引数として、ラッパ関数へのポインタで特定される、共有ライブラリ化ユーザプログラム内のラッパ関数を実行する。
【００２６】
なお、本発明の各構成要素は、その機能を実現するように形成されていればよく、例えば、所定の機能を発揮する専用のハードウェア、所定の機能がコンピュータプログラムにより付与されたデータ処理装置、コンピュータプログラムによりデータ処理装置に実現された所定の機能、これらの任意の組み合わせ、等として実現することができる。
【００２７】
また、本発明の各構成要素は、必ずしも個々に独立した存在である必要はなく、複数の構成要素が一個の部材として形成されていること、一つの構成要素が複数の部材で形成されていること、ある構成要素が他の構成要素の一部であること、ある構成要素の一部と他の構成要素の一部とが重複していること、等でもよい。
【００２８】
また、本発明のコンピュータプログラムおよびデータ処理方法は、複数の処理および動作を順番に記載してあるが、複数の処理および複数の動作を実行する順番は、その記載の順番に限定されるものではない。このため、本発明のコンピュータプログラムおよびデータ処理方法を実施するときには、その複数の処理および複数の動作の順番は内容的に支障しない範囲で変更することができる。
【００２９】
さらに、本発明のコンピュータプログラムおよびデータ処理方法は、複数の処理および複数の動作が個々に相違するタイミングで実行されることに限定されない。このため、ある処理および動作の実行中に他の処理および動作が発生すること、ある処理および動作の実行タイミングと他の処理および動作の実行タイミングとの一部ないし全部が重複していてもよい。
【００３０】
また、本発明で云うデータ処理装置は、コンピュータプログラムを読み取って対応する処理動作を実行できるように、ＣＰＵ（Central Processing Unit）、ＲＯＭ（Read Only Memory）、ＲＡＭ（Random Access Memory）、Ｉ／Ｆ（Interface）ユニット、等の汎用デバイスで構築されたハードウェア、所定の処理動作を実行するように構築された専用の論理回路、これらの組み合わせ、等として実現することができる。
【００３１】
上述の各態様によれば、開発負荷を増加させることなく、様々な型の引数及び返り値を持つ関数を、或るコンピュータ装置からの指示により、他のコンピュータ装置上で実行させるデータ処理技術を提供することができる。
【図面の簡単な説明】
【００３２】
【図１】図１は、本発明の参考例の構成を示すブロック図である。
【図２】図２は、本発明の参考例の動作を示すフローチャートである。
【図３】図３は、本発明の第一の実施形態の構成例を示すブロック図である。
【図４】図４は、本発明の第一の実施形態の動作例を示すフローチャートである。
【図５】図５は、本発明の第二の実施形態の構成例を示すブロック図である。
【図６】図６は、本発明の第一の実施例のユーザプログラムを示す模式図である。
【図７】図７は、本発明の第一の実施例のクライアントライブラリを示す模式図である。
【図８】図８は、本発明の第一の実施例のサーバライブラリを示す模式図である。
【図９】図９は、本発明の第二の実施例のユーザプログラムを示す模式図である。
【図１０】図１０は、本発明の第二の実施例のクライアントライブラリにおける、引数が一つのユーザ関数を対象にしたラッパ関数を示す模式図である。
【図１１】図１１は、本発明の第二の実施例のクライアントライブラリにおける、引数が一つのユーザ関数を対象にした「rpc」関数を示す模式図である。
【図１２】図１２は、本発明の第二の実施例のクライアントライブラリにおける、引数が二つのユーザ関数を対象にしたラッパ関数を示す模式図である。
【図１３】図１３は、本発明の第二の実施例のクライアントライブラリにおける、引数が二つのユーザ関数を対象にした「rpc」関数を示す模式図である。
【図１４】図１４は、本発明の第二の実施例のサーバライブラリを示す模式図である。
【発明を実施するための形態】
【００３３】
〔参考例〕
まず、本発明の参考例を図１および図２を参照して以下に説明する。図１に示されるように、本発明の参考例のデータ処理システムは、クライアント１００とサーバ１１０とから構成される。
【００３４】
クライアント１００は、ユーザプログラム１０１、クライアントライブラリ１０３等を有する。ユーザプログラム１０１は共有ライブラリ化ユーザプログラム１０２を持つ。クライアントライブラリ１０３はユーザ関数シンボル名取得部１０４と通信部１０５とを有する。
【００３５】
サーバ１１０は、サーバライブラリ１１１を有する。サーバライブラリ１１１は、通信部１１２、ユーザ関数ポインタ取得部１１３、ユーザ関数実行部１１５等を有する。サーバライブラリ１１１は、クライアント１００から取得した共有ライブラリ化ユーザプログラム１１４をユーザ関数ポインタ取得部１１３からアクセスできる形で保持する。
【００３６】
これらは概略次のように動作する。ユーザは、ユーザプログラム１０１を記述し、ユーザプログラム１０１とクライアントライブラリ１０３とをリンクさせる。クライアントライブラリ１０３及びサーバライブラリ１１１は、ユーザプログラム１０１によらず同じものが利用される。
【００３７】
また、ユーザプログラム１０１をコンパイルすると、コンパイルされたユーザプログラム１０１は共有ライブラリとしても保存される。これは共有ライブラリ化ユーザプログラム１０２と表記される。
【００３８】
ユーザプログラム１０１内では、まず、初期化が行われる。この中で、ユーザプログラム１０１は、共有ライブラリ化ユーザプログラム１０２をクライアントライブラリ１０３に渡し、その共有ライブラリ化ユーザプログラム１０２を通信部１０５を経由してサーバ１１０に送信する。サーバ１１０は、通信部１１２でこれを受信し、受信された共有ライブラリ化ユーザプログラムをサーバライブラリ１１１の内部に共有ライブラリ化ユーザプログラム１１４として保持する。
【００３９】
初期化後、ユーザプログラム１０１は、サーバ１１０側で関数を呼び出す指示を行う。この関数を以後ユーザ関数と呼ぶ。ここで、ユーザプログラム１０１は、呼び出したいユーザ関数へのポインタと、その引数をクライアントライブラリ１０３に渡す。
【００４０】
クライアントライブラリ１０３では、ユーザ関数シンボル名取得部１０４が、そのユーザ関数ポインタが指すオブジェクトのユーザ関数シンボル名を取得する。この取得処理は、例えば、Linuxの場合、「dladdr」関数を用いることで実現可能である。
【００４１】
クライアントライブラリ１０３は、このシンボル名と与えられた引数とを通信部１０５を経由してサーバ１１０に送信する。サーバ１１０は、通信部１１２で、それらを受信する。
【００４２】
サーバ１１０は、ユーザ関数のシンボル名をユーザ関数ポインタ取得部１１３に渡す。ユーザ関数ポインタ取得部１１３は、初期化時に取得した共有ライブラリ化ユーザプログラム１１４、およびユーザ関数シンボル名から、呼び出すべきユーザ関数へのポインタを取得する。この取得処理は、例えば、Linuxの場合、「dlopen」関数で共有ライブラリをオープンし、そこで得られたハンドルと、ユーザ関数シンボル名を引数にして「dlsym」関数を呼び出すことで実現され得る。
【００４３】
ユーザ関数実行部１１５は、このユーザ関数ポインタと、引数を用いて、ユーザ関数を実行する。ユーザ関数実行部１１５は、その実行結果の返り値を通信部１１２を経由してクライアント１００に送信する。
【００４４】
クライアントライブラリ１０３は、通信部１０５で関数の実行結果である返り値を受信する。クライアントライブラリ１０３は、受信された返り値をユーザプログラム１０１に返す。このようにすることで、クライアント１００からの指示により、指定された関数をサーバ１１０側で実行することが可能となる。
【００４５】
次に、図１および図２を参照して本参考例の全体の動作について詳細に説明する。まず、ユーザプログラム１０１は、共有ライブラリ化ユーザプログラム１０２を指定して初期化を実行する（図２のステップ２０１）。
【００４６】
これにより、クライアントライブラリ１０３が、共有ライブラリ化ユーザプログラム１０２をサーバ１１０に送信する（ステップ２１１）。サーバライブラリ１１１は、これを受信し（ステップ２２１）、受信された共有ライブラリ化ユーザプログラムをサーバライブラリ１１１に登録する（ステップ２２２）。
【００４７】
次に、ユーザプログラム１０１が、サーバ１１０でユーザ関数を実行するために、ユーザ関数ポインタと引数をクライアントライブラリ１０３に渡す（ステップ２０２）。クライアントライブラリ１０３はこれを受け取り（ステップ２１２）、ユーザ関数ポインタを用いてユーザ関数シンボル名を取得する（ステップ２１３）。クライアントライブラリ１０３は、得られたユーザ関数シンボル名と引数をサーバ１１０に送信する（ステップ２１４）。
【００４８】
サーバライブラリ１１１は、ユーザ関数シンボル名と引数を受信し（ステップ２２３）、ユーザ関数シンボル名と登録しておいた共有ライブラリ化ユーザプログラム１１４からユーザ関数ポインタを取得する（ステップ２２４）。サーバライブラリ１１１は、このユーザ関数ポインタと引数を用いてユーザ関数を実行し（ステップ２２５）、その結果の返り値をクライアントライブラリ１０３に送信する（ステップ２２６）。
【００４９】
クライアントライブラリ１０３はこれを受信し（ステップ２１５）、その受信された返り値をユーザプログラム１０１に返す（ステップ２０３）。ステップ２０２から２０３を繰り返すことで、ユーザプログラム１０１は複数回、サーバ１１０側で関数を実行することが可能である。
【００５０】
〔第一の実施形態〕
次に、本発明の第一の実施形態について図３および図４を参照して詳細に説明する。
【００５１】
ところで、上述の参考例においては、サーバ１１０側で実行される関数の引数の数や型、返り値の型が指定できず、固定になっていた。その理由は、関数ポインタをユーザ関数ポインタ取得部１１３で取得するだけでは、その関数の引数の数や型の情報は得られないからである。第一の実施形態はこの点を解決している。
【００５２】
図３に示されるように、第一の実施形態におけるデータ処理システムは、クライアント３００とサーバ３１０から構成される。クライアント３００とサーバ３１０とは相互に通信する。
【００５３】
クライアント３００は、ユーザプログラム３０１とクライアントライブラリ３０３とを有する。ユーザプログラム３０１は共有ライブラリ化ユーザプログラム３０２を持つ。共有ライブラリ化ユーザプログラム３０２は、ユーザプログラム３０１が共有ライブラリとしてコンパイルされることにより得られる。
【００５４】
クライアントライブラリ３０３は、ユーザ関数シンボル名取得部３０４と、ラッパ関数ポインタ取得部３０５、ラッパ関数シンボル名取得部３０６、シリアライズ部３０７、デシリアライズ部３０８、通信部３０９等を含む。
【００５５】
ユーザ関数シンボル名取得部３０４は、関数へのポインタが指すオブジェクトのユーザ関数シンボル名を取得する。ラッパ関数ポインタ取得部３０５は、テンプレート関数として定義され、かつ、その内部でユーザ関数を実行するラッパ関数へのポインタを、ユーザ関数の引数及び戻り値の型をテンプレート引数として指定することにより、取得する。ラッパ関数シンボル名取得部３０６は、ラッパ関数へのポインタを用いて、ラッパ関数シンボル名を取得する。
【００５６】
サーバ３１０はサーバライブラリ３１１を有する。サーバライブラリ３１１は、通信部３１２、ラッパ関数ポインタ取得部３１３、ラッパ関数実行部３１５等を含む。通信部３１は、例えば、ユーザ関数シンボル名、ユーザ関数の引数に対応するデータ、ラッパ関数シンボル名、及び、ユーザプログラム及びラッパ関数が共有ライブラリとしてコンパイルされた共有ライブラリ化ユーザプログラムをクライアント３００から取得する。ラッパ関数ポインタ取得部３１３は、通信部３１により取得されたラッパ関数シンボル名を用いて、ラッパ関数へのポインタを取得する。
【００５７】
ラッパ関数実行部３１５は、ユーザ関数ポインタ取得部３１６、ユーザ関数実行部３１９、デシリアライズ部３１７、シリアライズ部３１８等を含む。ラッパ関数実行部３１５は、これら各処理部を用いて、ユーザ関数シンボル名とシリアライズされたユーザ関数の引数に基づいてラッパ関数を実行する。
【００５８】
サーバライブラリ３１１は、クライアント３００から取得した共有ライブラリ化ユーザプログラム３１４をラッパ関数ポインタ取得部３１３および、ユーザ関数ポインタ取得部３１６からアクセスできる形で保持する。ユーザ関数ポインタ取得部３１６は、初期化時に取得された共有ライブラリ化ユーザプログラム３１４およびユーザ関数シンボル名により呼び出すべきユーザ関数へのユーザ関数ポインタを取得する。ユーザ関数実行部３１９は、ユーザ関数ポインタと引数を用いてユーザ関数を実行する。
【００５９】
このような第一の実施形態におけるデータ処理システムの動作を説明する前に、ここで、上述の参考例と異なる「ラッパ関数」について説明する。この「ラッパ関数」を用いることにより、任意の型の引数、返り値を持つユーザ関数を実行することが可能となる。
【００６０】
ラッパ関数の実現のため、本実施の形態では、Ｃ＋＋のような、ジェネリックプログラミングの機能（Ｃ＋＋ではテンプレートと呼ぶため以下テンプレートと記述する）を使って関数を記述でき、かつ型を指定した関数の生成がコンパイル時に行われるプログラミング言語を用いる。
【００６１】
例えば、Ｃ＋＋のテンプレートを用いると、以下のような関数を記述できる。  
template <class T>
T add(T a, T b){return a+b;}
【００６２】
このような関数定義があった場合、
add<double>(1.0, 2.0)
と記述した場合、データ型「T」を「double」とした関数「add」が利用され得る。
【００６３】
これは、コンパイラが、
double add_double(double a, double b){return a+b;}
のような関数を内部で自動的に生成することで実現されている。
【００６４】
このような機能を用い、第一の実施形態は、ユーザ関数をその中から呼び出す「ラッパ関数」をテンプレート関数として導入する。そのテンプレート引数としてはユーザ関数の引数や返り値の型が定義される。
【００６５】
ラッパ関数自身の引数や返り値は、これらの型に依存せず、固定のものとする。したがって、ラッパ関数自身は、上述の参考例と同様の方法でサーバ３１０側で呼び出せる。一方、ラッパ関数は、テンプレート引数として得られたユーザ関数の引数や返り値の型を用い、ユーザ関数をその引数や返り値の型に応じて実行する。これによって、任意の型の引数、返り値を持つユーザ関数を実行できるようになる。
【００６６】
ラッパ関数は、引数として、ユーザ関数のシンボル名、ユーザ関数の引数をシリアライズしたものを取り、返り値としてシリアライズされたユーザ関数の返り値を返す。なお、ラッパ関数の返り値は、引数として取得されたポインタを用いて返されてもよい。以降の説明では、ラッパ関数の返り値は、返り値として返す例を用いる。
【００６７】
ここで、シリアライズとは、複数の変数を一つのバイト列等に変換する操作である。シリアライズされたバイト列等から元の変数を復元する操作をデシリアライズと呼ぶ。ラッパ関数は、テンプレート引数に指定された型を用いて、シリアライズされたデータからユーザ関数の引数をデシリアライズして復元する。
【００６８】
同様に、ラッパ関数は、テンプレート引数に指定された型を用いて、ユーザ関数の関数ポインタをその型に応じて取得する。そして、ラッパ関数は、この関数ポインタと引数を用いてユーザ関数を実行する。ユーザ関数の実行結果の返り値はシリアライズされラッパ関数の返り値として返される。
【００６９】
このようなラッパ関数は、テンプレート引数に応じ、ラッパ関数ポインタ取得部３０５で、ラッパ関数へのポインタを取得する部分で、コンパイラによって生成される。したがって、ラッパ関数は、共有ライブラリ化ユーザプログラム３０２、３１４にも含まれる。
【００７０】
このようなラッパ関数が定義されているとして、第一の実施形態の動作について説明する。まず、上述の参考例と同様に、ユーザはユーザプログラム３０１を記述し、ユーザプログラム３０１とクライアントライブラリ３０３とがリンクされる。
【００７１】
ここで、クライアントライブラリ３０３の一部は上記のテンプレート関数として定義されている。例えばＣ＋＋の場合、ヘッダファイル内に定義されており、コンパイル時にも利用される。
【００７２】
上述の参考例と同様に、ユーザプログラム３０１をコンパイルすると、コンパイルされたユーザプログラム３０１は共有ライブラリとしても保存される。これが、共有ライブラリ化ユーザプログラム３０２と表記される。
【００７３】
ユーザプログラム３０１内では、上述の参考例と同様に、まず、初期化が行われる。この中で、ユーザプログラム３０１は、共有ライブラリ化ユーザプログラム３０２をクライアントライブラリ３０３に渡し、共有ライブラリ化ユーザプログラム３０２を通信部３０９を経由してサーバ３１０に送信する。サーバ３１０は、通信部３１２でこれを受信し、受信された共有ライブラリ化ユーザプログラムをサーバライブラリ３１１内に共有ライブラリ化ユーザプログラム３１４として保存する。
【００７４】
続いて、ユーザプログラム３０１は、参考例と同様に、ユーザ関数ポインタと引数をクライアントライブラリ３０３に渡す。ここで、呼び出されるクライアントライブラリ３０３の関数は、テンプレート関数で実現され、ユーザ関数の引数や返り値の型をテンプレート引数として取る。
【００７５】
クライアントライブラリ３０３では、ユーザ関数シンボル名取得部３０４が、そのユーザ関数ポインタが指す、オブジェクトファイル内におけるオブジェクトのシンボル名を取得する。クライアントライブラリ３０３は、ユーザプログラム３０１から与えられた引数に対し、シリアライズ部３０７においてシリアライズを行う。
【００７６】
さらに、ラッパ関数ポインタ取得部３０５が、クライアントライブラリ３０３にテンプレート引数として与えられた型を指定して、ラッパ関数ポインタを取得する。そして、そのラッパ関数ポインタを用いて、ラッパ関数シンボル名取得部３０６が、ラッパ関数のシンボル名を取得する。
【００７７】
通信部３０９は、ラッパ関数シンボル名、ユーザ関数シンボル名、シリアライズされた引数をサーバ３１０に渡す。サーバ３１０は、通信部３１２を経由してこれらを受け取る。
【００７８】
サーバ３１０では、ラッパ関数ポインタ取得部３１３が、ラッパ関数シンボル名と共有ライブラリ化ユーザプログラム３１４から、ラッパ関数ポインタを取得する。サーバライブラリ３１１では、ラッパ関数実行部３１５が、この取得されたラッパ関数ポインタで特定されるラッパ関数を、ユーザ関数シンボル名と、シリアライズされたユーザ関数の引数とを引数として実行する。
【００７９】
ラッパ関数は、上述したとおり、共有ライブラリ化ユーザプログラム３１４とユーザ関数シンボル名とからユーザ関数ポインタを取得する。また、ラッパ関数は、シリアライズされた引数をデシリアライズし、ユーザ関数の引数を取得する。ラッパ関数は、取得されたユーザ関数の引数を用いて、上記ユーザ関数ポインタにより特定されるユーザ関数を実行し、その返り値をシリアライズし、シリアライズされた返り値をラッパ関数の返り値として返す。
【００８０】
シリアライズされた返り値は通信部３１２を経由してクライアント３００に返される。クライアント３００では、通信部３０９がこれを受け取り、デシリアライズ部３０８がその返り値をデシリアライズする。そして、デシリアライズされた返り値がユーザプログラム３０１に返される。
【００８１】
次に、図３および図４を参照して、第一の実施形態の全体の動作について詳細に説明する。まず、ユーザプログラム３０１が、共有ライブラリ化ユーザプログラム３０２を指定して初期化を実行する（図４のステップ４０１）。
【００８２】
これにより、クライアントライブラリ３０３が、共有ライブラリ化ユーザプログラム３０２をサーバ３１０に送信する（ステップ４１１）。サーバライブラリ３１１は、これを受信し（ステップ４２１）、受信された共有ライブラリ化ユーザプログラムをサーバライブラリ３１１に登録する（ステップ４２２）。
【００８３】
次に、ユーザプログラム３０１が、サーバ３１０でユーザ関数を実行するために、ユーザ関数ポインタと引数をクライアントライブラリ３０３に渡す（ステップ４０２）。クライアントライブラリ３０３は、これを受け取り（ステップ４１２）、ユーザ関数ポインタを用いてユーザ関数シンボル名を取得する（ステップ４１３）。
【００８４】
次に、クライアントライブラリ３０３は、取得された引数をシリアライズする（ステップ４１４）。そして、クライアントライブラリ３０３は、ラッパ関数のポインタを取得し（ステップ４１５）、ラッパ関数ポインタからラッパ関数シンボル名を取得する（ステップ４１６）。クライアントライブラリ３０３は、ユーザ関数シンボル名、シリアライズされた引数、ラッパ関数シンボル名をサーバ３１０に送信する（ステップ４１７）。
【００８５】
サーバ３１０は、ユーザ関数シンボル名、シリアライズされた引数、ラッパ関数シンボル名を受信する（ステップ４２３）。サーバライブラリ３１１は、受信されたラッパ関数シンボル名と共有ライブラリ化ユーザプログラム３１４とを用いてラッパ関数ポインタを取得し（ステップ４２４）、ユーザ関数シンボル名とシリアライズされた引数を用いてラッパ関数を実行する（ステップ４２５）。
【００８６】
実行されたラッパ関数内では、まず、ユーザ関数シンボル名と共有ライブラリ化ユーザプログラム３１４に基づいて、ユーザ関数ポインタが取得される（ステップ４２６）。そして、シリアライズされた引数がデシリアライズされ、引数が復元される（ステップ４２７）。
【００８７】
ラッパ関数は、これらを用い、ユーザ関数を実行する（ステップ４２８）。ラッパ関数は、ユーザ関数の返り値をシリアライズする（ステップ４２９）。このシリアライズされたユーザ関数の返り値は、ラッパ関数の返り値として返される、サーバライブラリ３１１は、シリアライズされたユーザ関数の返り値を、クライアント３００に送信する（ステップ４２１０）。
【００８８】
クライアントライブラリ３０３は、シリアライズされた返り値を受信し（ステップ４１８）、これをデシリアライズする（ステップ４１９）。そして、クライアントライブラリ３０３は、このデシリアライズされた返り値をユーザプログラム３０１に返す（ステップ４０３）。
【００８９】
次に、上述の第一の実施形態の作用及び効果について説明する。上述の第一の実施形態では、任意の型の引数、返り値を持つユーザ関数を内部で呼び出すラッパ関数がテンプレート関数として定義され、ラッパ関数自身の引数、返り値の型が固定され、このラッパ関数がサーバ３１０側で呼び出される。これにより、第一の実施形態によれば、様々な型の引数、返り値を持つユーザ関数をサーバ３１０側で呼び出すことができる。
【００９０】
上述の第一の実施形態におけるデータ処理システムでは、クライアント３００側で共有ライブラリ化されたユーザプログラム３０２、及び、呼び出す関数のシンボル名がクライアント３００からサーバ３１０に送信され、サーバ３１０側で、シンボル名と共有ライブラリ化したユーザプログラム３０２から呼び出すべき関数ポインタが取得され、ユーザ関数が実行されるというように、ＲＰＣが実現される。これにより、第一の実施形態によれば、ＣやＣ＋＋といったネイティブコードにコンパイルする言語を採用し、ＩＤＬを用いず、ＲＰＣを記述することができる。
【００９１】
更に、第一の実施形態によれば、サーバ３１０側のプログラムとクライアント３００側のプログラムを別々に記述することなく、ＲＰＣを実現することができる。その理由は、サーバ３１０は、ユーザプログラムによらないサーバライブラリ３１１を用い、共有ライブラリ化したユーザプログラム３０２（３１４）を受信することで、ユーザプログラム内で定義された関数をサーバ３１０側で実行するからである。更に、第一の実施形態によれば、ＯＳレベルでの動作を想定していないので、ＯＳの変更が必要なく、既存ＯＳ上で動作するライブラリとして実現することができるので、有用性が高い。
【００９２】
〔第二の実施形態〕
次に、第二の実施形態について図５を参照して詳細に説明する。第二の実施形態におけるデータ処理システムは、図５に示されるような、ハードウェア構成を持つ。クライアント５００は、少なくとも１つのコンピュータ５０１、記憶媒体５０２等から構成され、サーバ５１０は、少なくとも１つのコンピュータ５１１、記憶媒体５１２等から構成される。
【００９３】
コンピュータ５０１及び５１１は、相互に接続される、ＣＰＵ（Central Processing Unit）、メモリ、入出力インタフェース（Ｉ／Ｆ）等を有する。記憶媒体５０２及び５１２は、例えば、ハードディスク、ＣＤ、ＤＶＤ、ブルーレイ等のような媒体である。記憶媒体５０２及び５１２は、上述の第一の実施形態におけるユーザプログラム３０１、共有ライブラリ化ユーザプログラム３０２、クライアントライブラリ３０３、サーバライブラリ３１１等を格納する。コンピュータ５０１及び５１１は、記憶媒体５０２及び５１２に格納されるそれらプログラムを読出し、読み出されたプログラムをＣＰＵで実行することにより、上述の第一の実施形態におけるデータ処理システムを実現する。
【００９４】
第二の実施形態では、第一の実施形態におけるクライアントライブラリ３０３に含まれる、ユーザ関数シンボル名取得部３０４、ラッパ関数ポインタ取得部３０５、ラッパ関数シンボル名取得部３０６、シリアライズ部３０７、デシリアライズ部３０８、及び通信部３０９は、ソフトウェア要素として実現される。これらソフトウェア要素は、例えば、クライアントライブラリ３０３に含まれるモジュール又はコンピュータ５０１のＯＳ（図示せず）で提供されるモジュールがＣＰＵにより実行されることにより実現される。
【００９５】
また、第二の実施形態では、第一の実施形態におけるサーバライブラリ３１１に含まれる、ラッパ関数実行部３１５、ラッパ関数ポインタ取得部３１３、通信部３１２、ユーザ関数実行部３１９、シリアライズ部３１８、デシリアライズ部３１７、ユーザ関数ポインタ取得部３１６も、ソフトウェア要素として実現される。これらソフトウェア要素は、例えば、サーバライブラリ３１１に含まれるモジュール又はコンピュータ５１１のＯＳ（図示せず）で提供されるモジュールがＣＰＵにより実行されることにより実現される。
【００９６】
また、上述の第一の実施形態では特に明記はしなかったが、ユーザプログラム３０１、クライアントライブラリ３０３、サーバライブラリ３１１等を実行形式（ネイティブコード）に変換するソフトウェアであるコンパイラ（リンカ等も含む）も、コンピュータ５０１又５１１は保持する。第一実施形態における各処理部が実現されるにあたり、これらコンパイラがコンピュータ５０１又は５１１で実行される。
【００９７】
よって、第二の実施形態では、第一の実施形態の動作の説明における、動作主体（ユーザプログラム３０１、クライアントライブラリ３０３、サーバライブラリ３１１、ラッパ関数など）はＣＰＵに置き換えることができる。この点、以下の実施例でも同様である。
【００９８】
[実施例]
次に、具体的な本発明の実施例の動作を図６から図１４を用いて以下に説明する。ここでは、実施例として、Linux ＯＳ上で実行される、Ｃ言語あるいはＣ＋＋言語により記述されたソースコードが例示される。但し、各図に示されるソースコードは、部分的に例示されたものであるため、そのまま動作するものではない。
【００９９】
図６から図８に、第一の実施例が示される。図６はユーザプログラムを示し、図７はクライアントライブラリを示し、図８はサーバライブラリを示す。
【０１００】
図６のユーザプログラムでは、「userfunc1」及び「userfunc2」という関数（ユーザ関数）が定義されている。これらがサーバで実行したい関数である。参考例では、これらの関数の引数の数や型、返り値の型は固定となる。本参考例における各関数は、「int」型の引数を一つとり、「int」型の返り値を返す関数として定義されている。
【０１０１】
main()の中では、まずIPアドレス等を含むサーバの情報がNode型変数である「server」に取得される。Node型はライブラリ内で定義されているものとする。
【０１０２】
次に、関数「init」が呼び出されることにより、初期化が行われる。関数「init」の引数には、変数「server」と、共有ライブラリ化ユーザプログラムのファイル名が渡される。すなわち、関数「userfunc1」及び「userfunc2」が、共有ライブラリとしてこのファイル名で示されるファイル内に存在することになる。
【０１０３】
次の行の記述「rpc(server, userfunc1, 1)」により、サーバ側で関数「userfunc1(1)」が呼び出され、その返り値が「rpc」関数の返り値として得られる。この例の場合は「2」が返り値として返る。関数「userfunc2」についても同様に実行される。
【０１０４】
次に、図７を参照し、クライアントライブラリ３０３について説明する。クライアントライブラリ３０３では、ユーザプログラムから呼び出される関数「init」および関数「rpc」が定義されている。
【０１０５】
「init」関数が実行されると、サーバに共有ライブラリ化ユーザプログラムが送信される。そのため、「init」関数内では、まず、「connect_to_server」関数が実行されることにより、サーバへの接続が実現される。この実施例では、この関数は、Node型変数を受け取り、このNode型変数で示されるサーバに接続した後、ソケットを示すファイルディスクリプタを返す。
【０１０６】
次に、ファイル名で指定された共有ライブラリ化ユーザプログラムが、「raed_from_file」関数により読み取られる。この関数は、ファイルからその内容を読み取り、読み取られた内容を第一引数で与えられた「char」型のポインタが指すメモリ領域に書き込む。なお、ここでは、変数の宣言やメモリ確保及び解放などは省略されている。そして、読み込んだバイト数が戻される。
【０１０７】
次に、「write_to_socket」関数がサーバにファイルの内容を送信する。この関数は、ソケットと送信すべきデータが入った「char」型のポインタ、およびそのサイズを指定することで、データをサーバに送信する。最後に、「close_connection」関数が呼び出される。この関数は、「connect_to_server」関数で作成されたソケットをクローズする。
【０１０８】
次に、「rpc」関数について説明する。「rpc」関数の中では、「get_symbol」関数が利用されているため、これについて、まず説明する。「get_symbol」関数は、関数ポインタを受け取り、ＯＳが提供する「dladdr」関数を呼び出すことで、関数ポインタのシンボル名を取得する。「dladdr」関数には、関数ポインタと、ＯＳが定義する「Dl_info」型の変数へのポインタを渡すことで、「Dl_info」型変数の「dl_sname」メンバにその関数のシンボル名が返される。
【０１０９】
次に「rpc」関数の動作について説明する。「rpc」関数は、上述の「get_symbol」関数を用い、引数として与えられた関数ポインタのシンボル名を取得する。次に、上述と同様に「connect_to_server」関数を用いてサーバに接続し、ソケットのファイルディスクリプタを取得する。
【０１１０】
そして、「rpc」関数は、「write_to_socket」関数を用いて、まず、ユーザ関数シンボル名をサーバに送信する。そのため、引数に、ソケットのファイルディスクリプタ、ユーザ関数シンボル名、及びそのサイズが渡される。
【０１１１】
次に、「rpc」関数は、引数をサーバに送信する。そのため、「write_to_socket」関数の引数として、ファイルディスクリプタと、引数を「char」型のポインタ型にキャストしたもの、そしてsizeof(int)（この例では「int」型）が渡される。
【０１１２】
次に、「rpc」関数は、「read_from_socket」関数を用い、実行結果をサーバから受け取る。この関数は、ソケットのファイルディスクリプタと、「char」型のポインタを受け取り、実行結果のデータをサーバから受け取る。続いて、「rpc」関数は、変数「ret」に、サーバから受け取った値（変数「buf」の値）を「int」型にキャストした上で設定する。最後に、「rpc」関数は、「close_connection」関数でソケットをクローズし、変数「ret」の値をrpc関数の返り値として返す。
【０１１３】
次に、図８を参照してサーバライブラリの動作について説明する。
【０１１４】
サーバライブラリでは、まず、「accept_connection」関数が、クライアントからの接続を受け付ける。図８の例では、この関数は、クライアントによる「connect_to_server」関数の実行に応答し、接続を確立する。この関数は、返り値として、ソケットのファイルディスクリプタを返す。なお、接続ごとにプロセスがフォークされ、接続ごとに別プロセスが生成されてもよい。この場合、親プロセスは、「accept_connection」関数の実行に戻り、子プロセスは以下の処理を行う。
【０１１５】
サーバは、この接続を用い、クライアントから共有ライブラリ化ユーザプログラムを「read_from_socket」関数で受信する。「read_from_socket」関数は返り値として読み込んだバイト数を返す。
【０１１６】
次に、メモリ上に読み込んだ共有ライブラリ化ユーザプログラムをファイルに書き込むため「write_to_file」関数が呼び出される。この関数は、ファイル名と、共有ライブラリ化ユーザプログラムが読み込まれたメモリ領域へのポインタ、そのサイズを指定して、共有ライブラリ化ユーザプログラムを引数のファイル名により示されるファイルに書き込む。ここでは、書き込み先のファイル名として「/tmp/tmpfile.so」が指定されている。
【０１１７】
そして、ＯＳが提供する関数である「dlopen」により、この共有ライブラリがオープンされる。引数には書き込まれたファイルのファイル名と、「dlopen」の動作を決めるフラグが指定される（ここではRTLD_LAZYを指定している）。「dlopen」の返り値は「ハンドル」であり、これを後で利用する。
【０１１８】
そして、「close_connection」関数が呼び出され、クライアントとの接続がクローズされる。この後、サーバはクライアントからのユーザ関数実行要求を受け付けるためのループを実行する。
【０１１９】
まず、サーバは、「accept_connection」関数により、クライアントからの接続を受け付ける。なお、あるユーザ関数実行中にも他のユーザ関数実行要求を同時に受け付けるため、以下のユーザ関数実行のための処理が別スレッドで行われるようにしてもよい。
【０１２０】
この場合、親スレッドは、「accept_connection」関数の実行に戻り、生成されたスレッドが以下の処理を行う。プロセスではなくスレッドを用いることで、ユーザ関数がグローバル変数に値を設定した場合などに、後で呼び出すユーザ関数呼び出しからその値を利用することができるようになる。
【０１２１】
次に、「read_from_socket」関数で、ユーザ関数シンボル名が受信される。更に続く「read_from_socket」関数で、引数が受信される。引数は、int型にキャストされる。続く、「typedef」は、呼び出す関数の型を「functype」として定義する。この実施例では、「functype」は、「int」型の値を引数にし、「int」型の値を返す関数へのポインタ型として定義されている。
【０１２２】
そして、サーバは、ＯＳが提供する関数である「dlsym」を呼び出すことで、呼び出すべき関数へのポインタを取得する。「dlsym」関数の引数は、「dlopen」関数の実行によって得られたハンドルと、関数のシンボル名である。「dlsym」関数の返り値として関数へのポインタが得られるので、このポインタが「functype」型の変数にキャストされ、代入される。
【０１２３】
そして、サーバは、この関数へのポインタに対し、引数を与えることにより、当該関数を実行する。この関数の返り値は、「write_to_socket」関数によって、クライアントに送信される。最後に、サーバは、「close_socket」関数で接続をクローズし、ループの先頭に戻る。
【０１２４】
次に、第二の実施例について図９から図１４を用いて説明する。図９はユーザプログラムを示し、図１０から図１３はクライアントライブラリを示し、図１４はサーバライブラリを示す。
【０１２５】
まず、図９のユーザプログラムについて説明する。これは第一の実施例とほとんど同じであるが、サーバで呼び出される関数の型および引数の数が変更可能になっている。すなわち、「userfunc1」関数は、「int」型の引数を一つとり、「int」型の値を返す関数であるが、「userfunc2」関数は、「double」型の引数を二つとり、「double」型の値を返す関数である。
【０１２６】
また、第二の実施例では、後述するとおり、「rpc」関数はテンプレート関数として実現されているが、コンパイラがデータ型を推論することが可能なため、呼び出し時に「rpc<int, int>」のようにデータ型を指定する必要は無い。
【０１２７】
次に、図１０から図１３を用いてクライアントライブラリを説明する。図１０及び図１１はユーザ関数の引数の数が一つの場合の定義を示し、図１２及び図１３はユーザ関数の引数の数が二つの場合の定義を示す。
【０１２８】
このように、第二の実施例では、ユーザ関数の引数の数に応じて、関数の定義が複数用意される。ここでは引数の数が二つまでを示すが、それ以上の引数の数に対応するためには、単純に引数の数を増やした定義が追加されれば良い。
【０１２９】
図１０および図１２はラッパ関数である「wrapper」の定義である。図１１および図１３は「rpc」関数の定義である。
【０１３０】
まず、図１０の「wrapper」関数について説明する。「wrapper」関数はテンプレート関数として定義されている。図１０の例は、ユーザ関数の引数の数が一つの場合の定義を示すため、テンプレート引数として、ユーザ関数の返り値のデータ型「R」と、引数のデータ型「T1」が指定されている。
【０１３１】
「wrapper」関数の引数は、ユーザ関数のシンボル名が設定される「symbol」、「dlopen」関数によって得られるハンドルが設定される「handle」、シリアライズされた引数である「input」、シリアライズされた返り値である「output」である。シリアライズされた返り値は、「wrapper」関数の中で作成され、呼び出し元に返されるため、「output」はポインタ引数である。
【０１３２】
第二の実施例では、Boostと呼ばれるライブラリ群により提供されるシリアライズライブラリを用いてシリアライズ機能が実現される例を説明する（ライブラリのバージョン1.35を元に説明する）。
【０１３３】
変数「input」の型は「binary_iarchive」であり、変数「output」の型は「binary_oarchive」であり、これらは、Boostのシリアライズライブラリが提供しているデータ型である。「binary_iarchive」型変数は、シリアライズされたデータをデシリアライズするために、「binary_oarchive」型変数は、変数をシリアライズするために用いられる。
【０１３４】
「wrapper」関数の中では、まず、ユーザ関数の型が「typedef」を用いて「functype」として定義される。図１０の例では、「functype」は、「T1」型の引数を取り、「R」型を返り値とする型として定義される。そして、ユーザ関数のシンボル名が設定される「symbol」と、「dlopen」関数によって得られるハンドルが設定される「handle」とを引数として「dlsym」関数が呼び出されることで、ユーザ関数ポインタが取得される。これが「functype」型にキャストされ、変数「ｆ」に代入される。
【０１３５】
更に、引数のデータ型である「T1」型の変数「a1」、及び、返り値のデータ型である「R」型の変数「ret」が定義される。そして、引数である変数「input」がデシリアライズされたデータが、変数「a1」に代入される。Boostのシリアライズライブラリでは、このデシリアライズ操作は「＞＞」として定義されている。
【０１３６】
続いて、変数「a1」を引数としてユーザ関数「f」が実行され、返り値が変数「ret」に保存される。返り値となる変数「output」には、変数「ret」がシリアライズされたデータが入力される。このシリアライズ操作はBoostのシリアライズライブラリでは「＜＜」として定義されている。
【０１３７】
次に、図１１を参照して、「rpc」関数について説明する。「rpc」関数もテンプレート関数として定義されている。図１１の例は、ユーザ関数の引数の数が一つの場合の定義を示すため、テンプレート引数として、ユーザ関数の返り値のデータ型「R」と引数のデータ型「T1」が指定されている。
【０１３８】
「rpc」関数の引数は、第一の実施例の場合と同様であるが、「rpc」関数がテンプレート関数として定義されているため、引数のデータ型に制約は無い。「rpc」関数の中では、まず、ラッパ関数ポインタが取得される。このとき、テンプレート引数として与えられたデータ型が、「wrapper<R,T1>」と指定されることで、そのデータ型に応じたラッパ関数ポインタが取得される。コンパイラは、このラッパ関数ポインタが取得された時点で、テンプレート引数「R, T1」に応じた「wrapper」関数の定義を作成する。
【０１３９】
次に、上記で得られたラッパ関数のシンボル名が取得される。これには第一の実施例で用いた「get_symbol」関数が利用される。次に、「rpc」関数の引数として与えられたユーザ関数ポインタを引数として「get_symbol」関数を呼び出すことで、ユーザ関数シンボル名が取得される。
【０１４０】
そして、引数「a1」がシリアライズされる。Boostのシリアライズライブラリでは、シリアライズした結果を「string」型として受け取る場合、標準ライブラリの「ostringstream」型の変数を引数として、「binary_oarchive」型の変数が定義される。
【０１４１】
ここでは、「ostringstream」型の変数「os」が定義され、それを用いて「binary_oarchive」型の変数「input」が定義されている。そして、上述と同様、「＜＜」を用いて引数「a1」がシリアライズされる。
【０１４２】
次に、「rpc」関数は、「connect_to_server」関数を用いてサーバに接続する。この「connect_to_server」関数」により得られたソケットのファイルディスクリプタを引数として「write_to_socket」関数に与えることにより、ユーザ関数シンボル名が送信される。
【０１４３】
次に、シリアライズされた引数が送信される。シリアライズされた結果は、「ostringstream」型変数「os」に設定されているので、「str()」メンバ関数でまず「string」型として取り出され、さらに、「c_str()」メンバ変数で「char」型のポインタとして取り出される。
【０１４４】
シリアライズされた結果のサイズは、それを「string」型として取り出して、「length()」メンバ関数を呼び出すことにより得ることができる。続いて、ラッパ関数シンボル名が送信される。その後、シリアライズされた返り値が「read_from_socket」関数で取得される。
【０１４５】
この取得されたデータをデシリアライズするため、そのデータを「string」型に変換したものを引数として用いて標準ライブラリの「istringstream」型の変数「is」が定義される。そして、変数「is」を引数として用いて、「binary_iarchive」型の変数「output」が定義される。
【０１４６】
返り値を保存する変数「ret」が定義され、上述と同様に、「＞＞」を用いて変数「output」をデシリアライズしたデータが変数「ret」に設定される。最終的に、「close_connection」関数によりサーバとの接続がクローズされ、返り値「ret」がユーザプログラムに返される。
【０１４７】
図１２および図１３はユーザ関数の引数の数が二つの場合の定義を示す。以下、図１２の「wrapper」関数について、図１０で示されたユーザ関数の引数の数が一つの場合の定義との違いを中心に説明する。この場合、テンプレート引数は、返り値１つと引数２つとの合計３つになる。
【０１４８】
また、ユーザ関数の型において、引数の数が異なっている。これにより、引数のデシリアライズが２引数分になり、ユーザ関数も、２つの引数を用いて、呼び出されている。関数の名前は「wrapper」であり、図１０で示された引数が一つの場合と同じであるが、Ｃ＋＋において、これは許されている。
【０１４９】
次に、図１３の「rpc」関数について、図１１で示されたユーザ関数の引数の数が一つの場合の定義との違いを中心に説明する。「wrapper」関数の場合と同様、テンプレート引数が返り値１つと引数２つの合計３つになる。
【０１５０】
また、「rpc」関数自身の引数に関しても、ユーザ関数の引数が二つになるのに伴い、ユーザ関数ポインタの型が変更になり、またユーザ関数の引数が追加されている。「wrapper」関数ポインタを取得する部分でも、テンプレート引数の数が３つになっている。そして、引数をシリアライズする部分で、二つの引数がシリアライズされている。
【０１５１】
上述のように、図１０から図１２への変更及び図１１から図１３への変更と同様の変更を加えることによって、三つ以上の引数を持つユーザ関数についても定義を記述することが可能となる。
【０１５２】
次に、図１４を参照してサーバライブラリについて説明する。サーバライブラリは、引数の数によらず、同じものが用いられる。初期化の部分は第一の実施例と同じである。
【０１５３】
while文の中では、まず、クライアントからの接続が「accept_connection」関数で受け付けられる。ここで得られたソケットのファイルディスクリプタを用い、クライアントからユーザ関数のシンボルと、シリアライズされた引数が取得される。続いて、「binary_iarchive」型変数を作るため、取得された引数「buf」を「string」型に変換したデータを引数として用いることにより、「istringstream」型の変数「is」が定義される。更に、この変数「is」を引数として用いることにより、「binary_iarchive」型の変数「input」が定義される。この変数「input」は、後で「wrapper」関数の引数とされる。
【０１５４】
次に、ラッパ関数シンボル名がクライアントから取得される。これを元に、ラッパ関数ポインタが「dlsym」関数を用いて取得される。そして、「ostringstream」型の変数「os」が定義され、この変数「os」を引数に「binary_oarchive」型の変数「output」が定義される。この変数「output」は、「wrapper」関数の引数として、返り値をシリアライズした内容を受け取るために用いられる。
【０１５５】
そして、先ほど取得した「wrapper」関数のポインタを用いて、「wrapper」関数が実行される。このとき、「wrapper」関数の引数には、ユーザ関数シンボル名（「symbol」）、「dlopen」関数によって得られたハンドル（「handle」）、シリアライズされた引数を内部に持つ、「binary_iarchive」型の変数「input」、ユーザ関数の返り値をシリアライズしたものを保存するための「binary_oarchive」型の変数「output」へのポインタが与えられる。
【０１５６】
wrapper関数が実行されると、上述の「wrapper」関数の定義通り、引数がデシリアライズされ、ユーザ関数シンボル名からユーザ関数ポインタが取得され、デシリアライズした引数を用いてユーザ関数が実行され、返り値がシリアライズされて変数「output」に入れられる。
【０１５７】
これにより、「wrapper」関数終了後、シリアライズされた返り値の内容がクライアントに送信される。このとき、「ostringstream」型の変数「os」から「str()」メンバ関数で「string」型のデータが取り出され、さらに「c_str()」メンバ関数で、「char」型のポインタとしてデータが取り出される。取り出されるデータのサイズは、変数「os」のメンバ関数「str()」により取り出された「string」型のデータに対して、「length()」メンバ関数を呼び出すことで得られる。これらを引数に「write_to_socket」関数を呼び出すことで、クライアントにシリアライズされた返り値の内容が送信される。
【０１５８】
なお、本発明は本実施の形態に限定されるものではなく、その要旨を逸脱しない範囲で各種の変形を許容する。例えば、本発明は、ネットワークで結合された複数のサーバ上で並列に実行するプログラムを記述する用途に適用できる。また、ネットワークで結合された別のサーバ上の資源（ファイル等）を利用するプログラムを記述する用途にも適用可能である。
【０１５９】
なお、当然ながら、上述した実施の形態および複数の実施例は、その内容が相反しない範囲で組み合わせることができる。また、上述した実施の形態および実施例では、各部のプログラムなどを具体的に説明したが、そのプログラムなどは本願発明の要旨を逸脱しない範囲で各種に変更することができる。
【０１６０】
この出願は、２０１０年６月１７日に出願された日本出願特願２０１０−１３８３９８号を基礎とする優先権を主張し、その開示の全てをここに取り込む。
【図１】
2011158478.tif 000003
【図２】
2011158478.tif 000004
【図３】
2011158478.tif 000005
【図４】
2011158478.tif 000006
【図５】
2011158478.tif 000007
【図６】
2011158478.tif 000008
【図７】
2011158478.tif 000009
【図８】
2011158478.tif 000010
【図９】
2011158478.tif 000011
【図１０】
2011158478.tif 000012
【図１１】
2011158478.tif 000013
【図１２】
2011158478.tif 000014
【図１３】
2011158478.tif 000015
【図１４】
2011158478.tif 000016
【国際調査報告】
2011158478.tif 000017
2011158478.tif 000018
2011158478.tif 000019
2011158478.tif 000020