<このシリーズの、前の記事 | このシリーズの目次 |
本シリーズは、メインシリーズ、「UNO拡張機能(LibreOffice拡張機能またはApache OpenOffice拡張機能)を開発する」の記述をBasicマクロでのUNOの使用に適用するための、メインシリーズへの補完である
話題: UNO (Universal Network Objects)
話題: LibreOffice
話題: Apache OpenOffice
話題: LibreOffice Basicプログラミング言語
バイアス惑星の山あいの小川のほとりのある部屋でコンピュータースクリーンの前に座る-Hypothesizerと-Rebutter。
既に、シリーズ、「UNO拡張機能(LibreOffice拡張機能またはApache OpenOffice拡張機能)を開発する」があり、これはJavaによるUNOコンポーネント(UNOコンポーネントが何かを知るには、ここを参照)からなるUNO拡張機能を開発することについてのものだが、その基本的な考えのほとんどは、BasicマクロでUNOを使用することにもあてはまる。というのも、それらは、UNOを使用することについてであって、UNOは、基本的に言語に独立な仕様だから。
オーケー。
しかしながら、UNOのBasicマッピングにはいくつかの特別な扱いが与えられているので、我々はそれらを知らなければならない。
UNOのBasicマッピングにはなぜそのような特別な扱いが与えられているのか?
UNOに必須ないくつかの機能がLibreOffice Basicには欠けているので、それが必要なわけだ。もっとも目立つところでは、Basicにはインターフェースの概念がない。
ははあ。
前場と同じ。
あらかじめ言っておくが、我々は、大規模なロジックをBasicで実装する習慣にないので、BasicでUNOを使ってロジックを組むことについて、包括的なコメントをするつもりはない。
よく分からないな。
例えば、我々は、メインシリーズでスプレッドシートセルから読んだりスプレッドシートセルに書いたりする方法について取り扱ったが、このシリーズでは、そのような個別のロジックについて取り扱ったりはしない。
ああ、そこで記述されたロジックはBasicに適用できるはずだ。あとは、そのロジックがどのプログラミング言語で書かれているかというだけの問題だ。
だから、我々は、同じ議論を、ただBasicのコードでそれを示すというためだけに繰り返しはしない。
いいだろう。
実際のところ、Basicの大規模なコードを書こうという動機が私には全然ない。
なぜないのか?
JavaでUNOコンポーネントを作ることで、はるかにもっと広範囲のロジックをもっと効率的かつ堅牢に書けるから。Javaはより堅牢だ(より厳格にデータ型チェックをしてくれる)し、大規模なプログラミングにより適している(本格的なオブジェクト指向言語だ)し、機能もより豊富だ(BigDecimal、List、Set、Mapなどの豊富なデータ型がある、マルチスレッディングが行なえる、よりリッチなGUIが作れる、JNIを通してOSネイティブの機能にもアクセスできる)。
実のところ、我々はBasicにあまり通じていない。
そう、そしてそれが最大の理由だ。
ははあ。
また、我々は、個々のUNOコンポーネントの詳細を取り扱わない。というのも、それらは、メインシリーズで取り扱われている、または、取り扱われるであろうから。
それらもやはり、言語に独立だ。
このシリーズでは、UNOコンポーネント一般を呼び出す方法のみを取り扱う。
前場と同じ。
UNOを使用することについての汎用ルールは、「コンポーネントコンテキストを取得しろ。そうすれば、そのコンポーネントコンテキストを使って、許されていることは何でもできる」だ。
コンポーネントコンテキストはUNO環境へのハンドルであって、UNOサービスインスタンス(UNOサービスが何かを知るにはここを参照)としてのUNOオブジェクト(UNOオブジェクトが何かを知るにはここを参照)は、コンストラクタの引数としてもれなくそれを受け取り、外部UNOプログラムは、希望するUNO環境へ接続してそれを得る。それが、シリーズ、「UNO拡張機能(LibreOffice拡張機能またはApache OpenOffice拡張機能)を開発する」とシリーズ、「外部JavaプログラムでUNOを使用する(LibreOfficeまたはApache OpenOfficeのドキュメントを操作する)方法」で我々が学んだことだ。
しかし . . .
. . . しかし、何だ?
「しかし」というべきだったのかどうか。. . . 実際、Basicマクロにおいても、間違いなく、コンポーネントコンテキストを得られるし、コンポーネントコンテキストを使って、UNO環境を操作することができる。
それでは、何が問題なのか?
特に何も。実際、コンポーネントコンテキストは以下のようにして得られる。
-Hypothesizerは、LibreOfficeインスタンスを起動し、あるBasicモジュールを開き、そのモジュールに1つのSubを書く。
Sub testToGetDefaultComponentContext
Dim l_componentContext As Variant
l_componentContext = GetProcessServiceManager ().getPropertyValue ("DefaultContext")
End Sub
ふむ?まあ、どのようにコンポーネントコンテキストを得るにせよ、Javaでやったのと基本的に同じ方法でそれを使えるのだろう?
そうだ。. . . しかし . . .
. . . しかし、何だ?
うーん、以下が、BasicでUNOサービスのインスタンスを生成する典型的な方法だ。
-Hypothesizerは、先ほどのモジュールに別のSubを書く。
Sub testToCreatServiceInstanceInTypicalWay
Dim l_globalServicesManager As Variant
Dim l_arguments (0)
Dim l_heyUnoExtensionsUnoObject As Variant
l_globalServicesManager = GetProcessServiceManager ()
l_arguments (0) = "Good morning"
l_heyUnoExtensionsUnoObject = l_globalServicesManager.createInstanceWithArguments ("thebiasplanet.uno.heyunoextensionsunoextension.HeyUnoExtensionsService", l_arguments ())
End Sub
えー、コンポーネントコンテキストを得るのに先程使ったファンクション、'GetProcessServiceManager'は、実はグローバルUNOサービスマネージャー(グローバルUNOサービスマネージャーが何かを知るにはここを参照)を戻している。. . . 'createInstanceWithArguments'というメソッドは何だ?Javaでは'createInstanceWithArgumentsAndContext'というメソッドをコンポーネントコンテキストを渡して使ったが。
Javaでも前者のメソッドを使うことはできるが、そうしなかった、というのは、そういうやり方は最良ではないから。
なぜ?
コンポーネントコンテキストはUNO環境へのハンドルだと言ってきたが、実際には、コンポーネントコンテキストは、実行時環境としての、いくつかのプロパティのコンテナでもある。
ははあ . . .
コンポーネントコンテキストは、UNOオブジェクトの生成スタックに沿って伝達されると想定されているものだ。そして、コンポーネントコンテキストは、その途中で、変更されたバージョンで置き換えることができる。
例えば、あるUNOオブジェクトが生成されるとき、それは、あるコンポーネントコンテキストを受け取る。それは、必要であれば、そのコンポーネントコンテキストの変更バージョンを作る(いくつかのプロパティを追加、いくつかのプロパティを削除、いくつかのプロパティ値を変更、またはそれらの一部またはすべてを行なう)ことができ、最新版のコンポーネントコンテキスト(変更されていれば変更されたもの、変更されていなければ受け取ったもの)を、別の新たに生成されたUNOオブジェクトに渡す . . .
そう。'createInstanceWithArguments'を使うと、我々は、新たに生成されたUNOオブジェクトに最新版のコンポーネントコンテキストを渡さない。グローバルUNOサービスマネージャーがデフォルトコンポーネントコンテキストとして認識するコンポーネントコンテキストが新たに生成されたUNOオブジェクトに渡される。
そして、それが正に、上記の典型的なコードが行なっていることだ . . .
そうだ。
まあ、結局、Basicモジュールは、UNOコンポーネントではないから、特定のコンポーネントコンテキストを受け取らない、または、デフォルトコンポーネントコンテキストを受け取るのだと言えるのかもしれない。そして、そのデフォルトコンポーネントコンテキストを、新たに生成されたUNOオブジェクトに明示的に渡そうが渡さまいが、実際的には同じことだ、どちらにしろ、デフォルトコンポーネントコンテキストが渡されるのだから。
そのように思われる。
Basicランタイムは、デフォルトコンポーネントコンテキストが常に使われるという前提に立っているから、デフォルトコンポーネントコンテキストを直接には公開せず、グローバルUNOサービスマネージャーを公開している。そして、ほとんどの場合、使用するコンポーネントコンテキストを明示的に指定しなくても問題ない。しかし、特定のコンポーネントコンテキストを明示的に指定しなければならなかったり、したい場合は、いつでもそうできる。実際、以下のコードは問題なく動作する。
-Hypothesizerは先程のモジュールにあるSubを書く。
Sub testToCreatServiceInstanceExplicitlySpecifyingComponentContext
Dim l_componentContext As Variant
Dim l_globalServicesManager As Variant
Dim l_arguments (0)
Dim l_heyUnoExtensionsUnoObject As Variant
l_componentContext = GetProcessServiceManager ().getPropertyValue ("DefaultContext")
l_globalServicesManager = l_componentContext.getServiceManager ()
l_arguments (0) = "Good morning"
l_heyUnoExtensionsUnoObject = l_globalServicesManager.createInstanceWithArgumentsAndContext ("thebiasplanet.uno.heyunoextensionsunoextension.HeyUnoExtensionsService", l_arguments (), l_componentContext)
End Sub
特定のUNOサービス専用UNOサービスインスタンスファクトリー(「特定のUNOサービス専用UNOサービスインスタンスファクトリー」で我々が何を意味しているかを知るにはここを参照)を通してUNOサービスインスタンスを生成する場合はどうか?
同じだ。コンポーネントコンテキストを渡さなくても問題ないが、渡したければ渡すことができる。
コンポーネントコンテキストを受け取る第1引数の存在をただ無視すればよいということか、nullを第1引数に渡すのではなく?
そうだ。
ところで、我々がこれまで話してきたコンポーネントコンテキストは、Basicのコードが動作するLibreOfficeインスタンスのものだろう?
そう。それが、通常、Basicマクロが操作するように想定されているUNO環境だ。
別のUNO環境(例えば、リモートホスト上のUNO環境)のコンポーネントコンテキストは、どうすれば得られるのか?
Basicだけでそれを行なう方法を私は知らない。自分のUNOコンポーネントを通してそうすることはできるだろう、必要ならば。
ああ、シリーズ、「外部JavaプログラムでUNOを使用する(LibreOfficeまたはApache OpenOfficeのドキュメントを操作する)方法」の記述にしたがえばそうすることができる。
Basicでは、各UNOインターフェース(UNOインターフェースが何かを知るには、ここを参照)を代理するUNOプロキシ(UNOプロキシが何かを知るには、ここを参照)を明示的に得る必要はない。UNOオブジェクトに対して任意のメソッドをただ呼ぶことができる。
その機能(ここを参照)をサポートするようにUNOコンポーネントが作られた場合に限りそうだと記憶しているが。
そう、そのはずだ。
どのUNOオブジェクトを参照させる場合も、変数タイプにはVariantを使う。
ああ、Javaでは、UNOオブジェクト(厳密に言えば、UNOプロキシ)を参照させるのに、変数タイプとしてUNOインターフェースを使う。
Basicではインターフェースを使えないから、ただVariantを使って済ませる。
この参考文書は、変数タイプとしてObjectを使うべきでないと言っている、とはいえ、Objectは参考文書内の例で頻繁に使われているのだが。
つまり、参考文書が言うようにすべきであって、参考文書がしているようにではないということか . . .
UNOとBasicの間のデータタイプマッピングを知らなければならないだろう。
それは、ここで調べることができる。
- Apache OpenOffice Wiki. (2009/05/13). OpenOffice.org Basic. Retrieved from https://wiki.openoffice.org/wiki/Documentation/DevGuide/ProUNO/Basic/OpenOffice.org_Basic
<このシリーズの、前の記事 | このシリーズの目次 |