com4j¶
- 目次
- com4j
Windows COM形式ライブラリをJavaから利用するためのライブラリです。
公式サイト¶
http://com4j.kohsuke.org/index.html
リポジトリは次
https://github.com/kohsuke/com4j
インストール¶
mavenリポジトリからビルド済みのライブラリを取得します。
- http://central.maven.org/maven2/org/jvnet/com4j/com4j/
- http://central.maven.org/maven2/org/jvnet/com4j/tlbimp/
2015-08-14時点では、バージョン2.1が最新です。また、tlbimpはargs4jを利用しているので、args4jも取得します。
tlbimp-2.1 -> args4j-2.0.8
com4j-2.1.jar をzip解凍可能なツールで中からdllファイルを2つ抜き出します。
com4j-x86.dll, com4j-amd64.dll
以下が必要なファイル一式です。これを、適切なディレクトリに配置します(例、C:\java\com4j)
com4j-2.1.jar tlbimp-2.1.jar args4j-2.0.8.jar com4j-2.1-javadoc.jar tlbimp-2.1-javadoc.jar com4j-x86.dll com4j-2.1-sources.jar tlbimp-2.1-sources.jar com4j-amd64.dll
DLLをあらかじめjarファイルから抜いておく理由¶
com4jを利用するプログラムを実行する際、com4jのjarファイルと同じディレクトリにネイティブのライブラリ(com4j-x86.dllまたはcom4j-amd64.dll)が存在しないと、jarファイルの中からdllを自動で展開します。しかし、そのディレクトリにアプリケーション実行ユーザーが書き込み権限を持たない場合、dllが展開できず、com4jの初期化がエラーとなります。
NetBeansにおいても、通常の実行、デバッグ実行の際はライブラリ定義にあるcom4jを使用するのでライブラリ定義の場所が書き込み権限のないProgram Files下だとエラーとなります。
エラーメッセージを 表示する
利用方法¶
com4jは、COMインタフェースの型情報リポジトリ
COMインタフェース型に対応するJavaクラスを生成¶
COMインタフェースの提供する型に対応するJavaクラスを生成します。型情報は、COMのライブラリ(DLL、OCXなどの)ファイルから抽出します。
C:\work> java -jar C:\java\com4j\tlbimp-2.1.jar -o location -p geolocation %WINDIR%\System32\LocationApi.dll Generating definitions from LocationApiLib Unable to handle the type _SYSTEMTIME method GetTimestamp interface ILocationReport Unable to handle the type tag_inner_PROPVARIANT method GetValue interface ILocationReport :(中略) Unable to handle the type tagTLIBATTR method RemoteGetLibAttr interface ITypeLib Don't know how to print VT_UI4 as an Java literal Don't know how to print VT_UI4 as Java program code
生成されたJavaソースファイルは次のとおりです。
ClassFactory.java IStorage.java events IStream.java ICivicAddressReport.java ITypeComp.java ICivicAddressReportFactory.java ITypeInfo.java IDefaultLocation.java ITypeLib.java IDispCivicAddressReport.java LOCATION_DESIRED_ACCURACY.java IDispLatLongReport.java LOCATION_REPORT_STATUS.java IEnumSTATSTG.java package.html ILatLongReport.java tagCALLCONV.java ILatLongReportFactory.java tagDESCKIND.java ILocation.java tagFUNCKIND.java ILocationEvents.java tagINVOKEKIND.java ILocationReport.java tagSYSKIND.java ILocationReportFactory.java tagTYPEKIND.java IRecordInfo.java tagVARKIND.java ISequentialStream.java
メソッドのシグニチャについて¶
COMで定義されるメソッドは、通常戻り値型がHRESULTで、メソッドの処理結果は引数([out,retval])の1つとして実現します。
Javaでは、メソッドの処理結果を戻り値とすることが一般的です。
そこで、com4jではJavaの型を生成する際に、シグニチャをCOMの元の定義からアレンジして、メソッドの処理結果を戻り値として実現します。
http://com4j.kohsuke.org/runtime-semantics.html
プログラミング(Location APIを使ってGPSの位置を取得)¶
ILocation COMオブジェクトのインスタンス生成¶
ILocation location = ClassFactory.createLocation();
生成されたClassFactoryクラスのcreateLocationメソッドを使ってILocationインスタンスを生成します。
createLocationは、COM4J.createInstance(Class<T>, String) を呼んでおり、戻り値はnon-nullで、例外発生時はComExceptionをスローするとあります。
ILocationのrequestPermissionを呼び出し¶
GUID reportType = new GUID("7FED806D-0EF8-4F07-80AC-36A0BEAE3134"); // IID_ILatLongReport
location.requestPermissions(0, reportType, 1, 1);
C++/ATLでは、IID_ILocationReport というシンボル(GUID型)が利用可能ですが、生成されたJavaコードにはこのシンボルが存在しなかったので、ILocationReportインタフェースのIIDを調べて(生成されたILatLongReport.java ファイルを見ると次のように書かれているので)、そのGUID文字列を使用します。
@IID("{7FED806D-0EF8-4F07-80AC-36A0BEAE3134}")
public interface ILatLongReport extends com.torutk.location.ILocationReport {
requestPermissionの引数については次のように指定しています。
- 第1引数はC++/ATLではNULLを指定していたので、Javaでは0を指定
- 第2引数はC++/ATLではIID[]と配列ですが、生成されたJavaコードではGUIDとなっており、ここでは要素1つだけだったので配列ではなくGUIDを1つ指定
- 第3引数はC++/ATLでは第2引数の配列の要素数を指定していたので、ここでは1を指定(Javaでは第2引数が配列でないので2以上を指定するとダメかも)
- 第4引数はC++/ATLではTRUE(整数1のデファイン)を指定していたので、ここでは1を指定
ILcationのgetReportStatusを呼び出し¶
LOCATION_REPORT_STATUS status = location.getReportStatus(reportType);
if (status != LOCATION_REPORT_STATUS.REPORT_RUNNING) {
// 位置データの取得ができない状態の対処
}
LOCATION_REPORT_STATUS はenum型で、レポートの状態を判別できます。座標データが取得できるのはREPORT_RUNNINGのときです。
ILocationから位置(緯度経度)情報の取得¶
ILocationReport report = location.getReport(reportType);
ILatLongReport latLongReport = report.queryInterface(ILatLongReport.class);
if (latLongReport == null) {
// reportはILatLongReportインタフェースを実装していない
}
ILocationから、IID_ILatLongReportを指定して緯度経度の位置情報を取得します。ILocationインタフェースのGetReportメソッドはILocationReport型で取得されるので、緯度経度を取り出すためにILatLongReport型へQI(QueryInterface)して型変換(ダウンキャストのようなもの)します。
QIが出来ない場合はnullが返されるので、nullチェックをしておきます。
double latitude = latLongReport.getLatitude();
double longitude = latLongReport.getLongitude();
緯度(latitude)、経度(longitude)を取得します。
ILatLongReportにはほかにも高度(altitude)、および誤差(水平方向、高さ方向)を取得するメソッドもあります。
例外処理¶
生成されたJavaクラス群を利用する際に発生するエラーは、大抵は非チェック例外 ComException で通知されます。