.NET FrameWorkで作成されたDLL を JavaScript で使用する(2)
ほぼ一年近くも経って前回の続き。
・・・結局ダメ。
DLL内のクラスがCOM+用のインターフェースを搭載してないものと、そうでないものが混ざっており、まともに使えなかった。
よって別の方法を試すことにした。
Visual C++ Express Edition 2005 & Platform SDK で、DLLとJavaScriptの橋渡しをする COMのI/Fを実装するラッパーDLLを作成することにした。
結論
今度はうまくいった。ちゃんとJavaScriptかとCでコーディングされたDLL間でデータのやり取りや関数の呼出が行えるようになった。
ラッパーDLLを介して。
ラッパーDLLの作り方
準備
Visual C++ Express Edition 2005(と.NET Framework 2.0も) と Platform SDK をインストールする。(この辺のインストール方法の情報は調べればいくらでも見つかるので他のページにお任せ)
手順
1.プロジェクトの作成
「ファイル」→「新規作成」→「プロジェクト」→「CLR]→「クラスライブラリ」を選択してプロジェクトを作成する。
(※:今回はプロジェクト名を「COM_TestDll」として進める。以降「COM_TestDll」自分でプログラムを作成する際に自分で決定した文字列に置き換える)
2.プロジェクトの設定
1) 「ソリューション構成」(画面上部の右向き三角のアイコンの右隣のコンボボックス)を「Debug」→「Relese」に変更する2) ソリューションエクスプローラの「COM_TestDll」を右クリックし、プロパティ」を選択する。
すると「COM_TestDllプロパティ ページ」ダイアログボックスが開く
3) 「共通プロパティ-参照設定」を選択
4) 「新しい参照の追加」ボタンを押す
5) 「.NET」タブの「System.EnterpriseServices」を選択してOKボタンを押す。
3.キーファイルの設定(厳密なアセンブリ名の署名)
引き続き「COM_TestDllプロパティ ページ」ダイアログボックス内での設定。1) 「構成プロパティ-リンカ-詳細」を選択
2) キーファイルにキーファイル名を入力(今回はCOM_TestDll.snkとする)
文字列:
$(ProjectDir)COM_TestDll.snk
3) 「OK」ボタンを押し、ダイアログボックスを閉じる
4.プログラムの作成
4.1.AssemblyInfo.cppの編集
AssemblyInfo.cppを以下のように書き換える変更前:
[assembly:ComVisible(false)];
変更後:
[assembly:ComVisible(ture)];
に書き換える
4.2.COM_TestDll.cppの編集
1) ServicedComponentクラス使用のための宣言追加コード
using namespace System;
の次の行に以下の3行を追加
using namespace System::EnterpriseServices;
[assembly:ApplicationName("COM_TestDll")];
[assembly:ApplicationActivation(ActivationOption::Library)];
2) クラスの作成
デフォルトで「Class1」が設定されているので自分で好きなように書き換える。
※今回のプロジェクトでは「TestClass1」「TestClass2」とする。また、クラスは自分で好きに増やして良い)
3) ServicedComponentから先ほどのクラスを派生させる。
先ほどのクラス名の後ろに
: ServicedComponent
を付加する
例)
public ref class TestClass1 : ServicedComponent
4) コンストラクタの作成
クラス内にクラスメイト同じ名前の戻り値と引数なしの関数をpublicで追加する
例)
public:
TestClass1(void) { return; };
5) メンバの列挙
処理したい、変数や関数を列挙する
(※注意:COMに公開する条件として、メンバは全てpublicでなければならない)
5.キーファイルの作成
Visual C++ 2005 Express Editionインストールフォルダ内の「SDK\v2.0\Bin\sn.exe」を使用して
sn.exe -k COM_TestDll.snk
とタイプし、キーファイルを作成する。
その後、ソースファイルがあるフォルダへキーファイルを移動させる
7.レジストリへの登録
%SystemRoot%\Microsoft.NET\Framework\v2.0.50727\RegSvcs.exe COM_TestDll.Dll
(「v2.以降の"."と数字の組み合わせはインストールした.NET Framework 2.0のバージョンによりかわる)
とタイプし、
「インストールされたアセンブリ :」(以下省略)
と、Dllがインストールされれば成功
(※:アンインストールするには /u オプションをつけて同じコマンドを再度実行すればOK)
今後の課題など
Cで作成したDLL内の構造体やクラスは.NETで作成された構造体と互換性が無く、直接COMに渡すことができない。要するに、intやlong型などは直接JavaScriptとやり取りできるが、構造体の場合はそのメンバおのおのにアクセスするためには、それぞれインターフェース関数を作る必要がある。
・・・と思う(ひょっとしたらうまい方法があるのかも知らないが現在自分は知らない。)
よって、Cで作成したDLLのクラスが持つメンバ(また、そのメンバが持つメンバも含む)が多いと、その分インターフェース関数を用意するのがめんどくさい。
そこをもうちょっと何とかならないかと考えている。
.NET FrameWorkで作成されたDLL を JavaScript で使用する(1)
仕事で使っているハードウェアを、最近なんとなく解ってきたJavaScriptでいじってみたいと思い、JavaScriptでDLLの関数を呼ぶ方法を調べたが・・・。
ふつーのDLLはムリみたい*1。
基本的に ActiveXObject 関数で作成できるCOMコンポーネントのDLLのみ使用できるらしい。(今回の使用するDLLはCOMコンポーネントではないのが残念)
ただ、そのハードウェア制御用のドライバ(DLLでライブラリ提供)は .NET FrameWork 用のラッパーDLLを提供してくれているので、そこから何とかできないの?
ということで調べてみたら、なんとかできそうだということがわかった。
「できそう」というのは、まだ、DLL内のクラスをActiveXObjectとして生成することに成功した段階で、実際にDLLを動作させるまでにはいたっていない。
取り合えず必要な作業は以下。
- .NET FrameWork のインストール
- RegAsm.exe*2による対象DLLのレジストリへの登録
- RegAsm.exe /tlb オプション による対象DLLのタイプライブラリの作成&レジストリへの登録
- 対象のDLLを「%windir%\system32」にコピーする
以上。
最後の「対象のDLLを「%windir%\system32」にコピーする」をやらずに、任意の場所にDLLを配置する方法がとても難しい・・・らしい。
(自分はドライバ用のDLLを登録することが目的なので、system32にDLLをおき、いろんなJavaScriptから実行できたほうが都合が良いので、今回は深く調べなかった。)
この作業後に以下のコードを試し、try & catchでエラーが出ていないことを確認
function activeXtest(){
var obj;
try {
obj = new ActiveXObject("ライブラリ名.クラス名");
//[ライブラリ名]はDLLのファイル名ではない。
//"ライブラリ名.クラス名"は
//レジストリにキー"ProgId"として登録されたものが使用できる
} catch (e) {
alert("ActeiveXObject作成エラー:" + e);
}
try {
obj.メンバ関数名();
} catch (e) {
alert("メンバ関数呼び出しエラー:" + e);
}
return;
}
とりあえず、alartのダイアログボックスが表示されなかったので、大丈夫なんだろうけれども、今日は自宅で対象となるハードウェアが無いので、実際に関数が動作しているかが試せない。
・・・DLLが実際に動作するか早く試したいが、仕事が忙しいので確かめらるのが何時になることやら。
*1:逆にできちゃったら、ブラウザから間単にマシンのネイティブコード実行できたら危ないけど
*2:RegAsm.exeは.NET FrameWorkをインストールすると「%windir%\Microsoft.NET\Framework\vX.X.xxxx」(Xやxは.NET FrameWorkのバージョンにより異なる)に配置される