2007年7月11日水曜日

JavaでDLL連携

先々週ぐらいの金曜日、Windowsネイティブなアプリケーション(DLL)を呼び出すIdbAのデモコンポーネントを作る必要があり、開発のプレイングマネージャー(PM)にお願いして作ってもらった。
IdbAから呼び出す、と言っても、このレベルの話だと即ち「Javaから呼び出す」ということになるので、Javaとネイティブアプリケーションを繋ぐためのJava標準ライブラリ「JNI」を使用して作成してもらった。
デモなのでお客さんに見せるわけだが、一番手っ取り早くDLLと連携していることをわかってもらうには何がいいだろう?と話し合ったところ、「Windowsのデスクトップ背景画像を変えるのが一番わかりやすいんじゃないか?」ってことで、Windows側で公開されている壁紙変更APIを呼び出すためのDLLをVCで作成し、それをJavaからJNIで呼び出すことにした。
このDLL作成自体は、ms2氏の協力のもあってサックリ出来た。
作成後、自分のPCで動作確認し、満を持してお客さん先へ行き、PCに入れて実際の動作検証。

動かない。

起動したコマンドプロンプトを見てみると、ワシャっと例外が発生している。
「このアプリケーションの構成が正しくないため、アプリケーションを開始できませんでした。アプリケーションを再度インストールすることにより問題が解決する場合があります」

どうやらVCで作成した自前DLLがこのメッセージを出しているらしい。
なぜだ。他のPCではまず間違いなく動くのに、なぜ肝心のお客さん先のPCで動かないのだ。
違いといえば、お客さん先PCはWindows XPのServicePack 1を使っている、ということ。

とりあえず持ち帰り、PMにも伝え、調査開始。こんな調査をするのはプログラムを書いていた時以来。
先のDLLが出したメッセージ「このアプリケーションを~」というメッセージそのものでググってみると、かなり沢山ヒットして、どうやら多くの人々が悩むポイントらしきことはわかった。
で、その人たちの出してくれた情報(大抵は質問掲示板のやり取り)を丹念に読んでいくと、どうやらコンパイルオプションがネックらしい。Visual Stadioで作成したコードをバイナリにする際、どういった形式でバイナリにするかっていうのをオプションで指定できて、「/MDd(マルチスレッドデバッグ)」ではなく「/MD(マルチスレッド)」、つまりデバッグモードではなくリリースモードでDLLを作成しないと、作成した以外のPC環境では動かないようだ。
ところがそれをPMに伝えたところ、「確かにリリースモードで作成した」とのこと。

もはや悩んでいても仕方ない、実際のお客さんのPCと同じ環境を作って試してみよう、ということに。ただしWindows XP ServicePack 1の環境を作るのは、なかなか難しい。空いてるPCを探し、素のWindows XPを探し、ServicePack1のCDを探し。
各所を駆けずり回り、すべてゲットしてOSインストールから開始。
時刻は既に21時。でも、これを解決しないまま土日を過ごすのはイヤなので、根気よく環境の作成を続ける。途中でPMが、「どうやらServicePack1だと、/MDでもダメで、/MTじゃないとダメっていう情報を見つけた」と。それでDLLを作り直してもらい、ようやく環境が出来上がったところで、まずは以前までのDLLを動かしてみる。
バッチリお客さん先の環境と同じ内容でオチた。
DLLを、新バージョンに差し替えて再度実行。

動いたっ!
動いたー!!
動いたぞーーー!!!

思わずPMと熱く固い握手。
そして、心底みなぎり、湧き上がる充実感。

マイクロソフトの罠のせいで、久々にアツい夜を過ごせました。

参考リンク:VCのコンパイルオプションのわかりにくい説明

http://msdn2.microsoft.com/ja-jp/library/2kzt1wy3(VS.80).aspx

3 件のコメント:

匿名 さんのコメント...

ここはトラックバックできないのかな?
今回の件についてキミ経由でPM殿にお伝えしておいて欲しいのだが。

Takamitsu Kashiwa さんのコメント...

なんか、このブログよくわかんなくって…。
文字化けしたりするし。

で、お伝えすべきことは?

匿名 さんのコメント...

りょーかい。

http://ms2.seesaa.net/article/48076444.html
ここに書いておきました。

今回は1の解決をしたのだろうけど、
今後何かで2や3が必要になるかな?と思って。