COMコンポーネントの設計と応用(七)――コンパイル、登録、呼び出し

8467 ワード

この文書は次のとおりです.http://www.vckbase.net/index.php/wv/1218
一、前言
前回はATLで最初のCOMコンポーネントプログラムを書きましたが、今回は主にコンパイル、ブック、呼び出し方法を紹介します.サンプルプログラムをダウンロードしましたか?まだダウンロードされていない場合は、vc 6.0のユーザーポイント、vc.netのユーザーポイントはこちらです.
二、コンパイルについて
2-1最小依存
「最小依存」は、コンパイラがATLで使用する必要がある関数の一部をターゲットプログラムに静的に接続することを示します.これにより、ターゲットファイルのサイズはやや大きくなりますが、独立性が強く、インストールが便利です.逆にシステムの実行にはATL.DLLファイルのサポートが必要です.「最小依存」に設定するにはどうすればいいですか?答えは、定義済みマクロ「_ATL_DLL」を削除し、操作方法は図1、図2を参照してください.
図一、vc 6.0での設定方法
図二、vc.net 2003において、設定方法
2-2 CRTライブラリ
ATLコンポーネントプログラムでCRTのランタイムライブラリ関数(例えば、sqrt()を2乗開く)が呼び出された場合、コンパイル時に「error LNK 2001:unresolved external symbol_main」とエラーが発生する可能性があります.どうしよう?定義済みマクロ「_ATL_MIN_CRT」を削除!操作方法も図1、図2を参照してください.(vc.net 2003のこの項目の属性は「ATLでCRTを最小使用する」と呼ばれています)
2-3 MBCS/UNICODE
これは言うまでもなく、事前定義マクロでは、それぞれ_MBCSまたは_UNICODE.
2-4 IDLのコンパイル
COMは設計初期に、言語間呼び出しを実現することを目標としていた.言語間である以上、コンポーネントのインタフェース記述は、どの言語環境でも認識されなければならない.どうしよう?.hファイルで説明する?------C言語プログラマーが笑って、便利ですね.BASICプログラマーは泣きました:-(そのため、マイクロソフトは新しいファイルフォーマット---IDLファイル(インタフェース定義記述言語)を使用しました.IDLはテキストファイルで、その言語文法は比較的簡単で、Cに似ています.具体的なIDLファイルの説明は、次の「COMコンポーネント設計と使用すべき(8)の新しいインタフェースの追加」を参照してください..IDLはコンパイルされ、バイナリを生成する等価型ライブラリファイルTLBが他の言語に提供されて使用される.図3は、ATL COMプログラムのコンパイルプロセスを示す.
図3、ATLコンポーネントプログラムのコンパイル過程
説明1:コンパイル後、タイプライブラリはTLBファイルとして単独で存在し、ターゲットファイルのリソースにも保存される.したがって、将来#importがタイプライブラリを導入する際に、TLBファイルを指定することも、ターゲットファイルを指定することもできる.
説明2:私たちはC/C++のプログラマーとして、まだ幸せです.IDLのコンパイル後、わざわざC言語形式のインタフェースファイルを提供してくれたからです.
説明3:IDLコンパイル後にエージェント/スタブソースプログラムを生成します.dlldata.c、xxx_p.c、xxxps.def、xxxps.makがあります.NMAKE.EXEで再コンパイルして、本物のエージェント/スタブDLLターゲットファイルを生成できます(注1).
三、登録について
状況1:ATLを使用してコンポーネントプログラムを作成する場合、登録は私たちが責任を負う必要はありません.コンパイルに成功すると、IDEは自動的に登録してくれます.
ケース2:MFCを使用してコンポーネントプログラムを作成する場合、コンパイラはあなたがCOMコンポーネントを書いているかどうか分からないため、自動的に登録することはできません.この場合、メニュー「ToolsRegister Control」を実行して登録することができます.
ケース3:COM機能を持つEXEプログラムを書くとき、登録する方法はこのプログラムを1回実行することです.
ケース4:サードパーティが提供するコンポーネントプログラムを使用する必要がある場合、コマンドラインに「regsvr 32.exeファイル名」を実行して登録することができます.ちなみに、逆登録の方法は「regsvr 32.exe/uファイル名」です.
ケース5:プログラム(インストーラなど)に登録する必要がある場合:01. typedef   HRESULT   (WINAPI * FREG)(); 02. TCHAR   szWorkPath[ MAX_PATH ]; 03.
  04. ::GetCurrentDirectory(  sizeof (szWorkPath), szWorkPath );     // 05. ::SetCurrentDirectory( );   // 06.
  07. HMODULE   hDLL = ::LoadLibrary( );   // 08. if (hDLL) 09. { 10. FREG lpfunc = (FREG)::GetProcAddress( hDLL, _T( "DllRegisterServer" ) );   // 11. // , "DllUnregisterServer" 12. if   ( lpfunc )   lpfunc();    // 。 , 13. ::FreeLibrary(hDLL); 14. } 15.
  16. ::SetCurrentDirectory(szWorkPath);   //
上記の例では、作業ディレクトリを切り替えるコード部分を簡略化できる場合が多いです.しかし、このコンポーネントをマウントする際に、依存しなければならないDLLを同時にロードする必要がある場合、自身のプログラムのBUGによって正しく位置決めできない可能性があります.咳......やはり自分で書いたプログラムで、そのエラーを補うようにしましょう......誰が私たちを良い人にしますか?ねえ、誰が私たちのレベルを彼より高くして、誰が私たちをvckbaseの上で“ランキングの目”にさせます......
四、コンポーネント呼び出しについて
総じて、コンポーネント・プログラムを呼び出すには、次のような方法があります.
#includeメソッド
IDLのコンパイル後、C/C++プログラマーの使用を容易にするために、xxx.hとxxx_i.cファイルが生成されます.私たちは本当に幸せで、直接#includeの後で使用することができます
#importメソッド
一般的な方法として、vcは包装クラスを生成し、呼び出しをより便利にします.
タイプライブラリパッケージクラスのロード方法
コンポーネントがIDispatchインタフェースを提供している場合は、この方法でコンポーネントを呼び出すのが一番簡単です.しかし、IDispatchはまだ話していません.後の文章を読むしかありません.
ActiveXパッケージのロード方法
ActiveXはまだ紹介されていないので、後で話しましょう.
サンプルプログラムをダウンロードしたら、使用方法を1つずつ参照してください.

方法
簡単な説明
1
#include
最も基本的なAPI方式でコンポーネントを呼び出し、呼び出し原理を熟知させる.
2
#include
ほとんどの場合、API方式を使用し、CComBSTRを使用して文字列の使用を簡略化します.
3
#include
スマートポインタCComPtr<>の使い方を示す
4
#include
スマートポインタCComPtr<>とCComQIPtr<>のブレンドの使用方法を示します
5
#include
スマートポインタCComQIPtr<>の使い方を示す
6
#include
スマートポインタの解放方法を示す
7
#import
vcパッケージのスマートポインタIxxxPtr、_bstr_t、_variant_tの使用方法と例外処理
8
#import
import後のネーミングスペースの使い方
サンプルプログラムにはコメントが書かれています.MSDNの関数の説明をよく読んで、参考にしてください.ここでは、「スマートポインタ」について説明します.
元のインタフェースポインタを操作するのが面倒なので、引用記数、API呼び出し、異常処理を自分で制御する必要があります.そこでATLは2つのスマートポインタのテンプレートパッケージクラス、CComPtr<>とCComQIPtr<>を提供し、この2つのクラスが宣言されています.CComQIPtr<>はCComPtr<>のすべての機能を含んでいるので、私たちは完全にCComQIPtr<>を使ってスマートインタフェースを使用することができますポインタ、唯一説明したいのは、CComQIPtr<>演算子のリロード機能を使用しているため、QueryInterface()関数を自動的に呼び出すことができます.そのため、CComQIPtr<>唯一の欠点は、IUnknown*ポインタを定義できないことです.1. // smart pointer, , sp 2. CComPtr < IUnknown > spUnk;    // 3. // IFun 4. CComPtr < IFun > spFun;    // 5. CComQIPtr < IFun > spFun;  // 6. CComQIPtr < IFun, &IID_IFun > spFun;   // 7. CComQIPtr < IUnknown > spUnk;  // !CComQIPtr IUnknown
スマートポインタに値を割り当てる方法:01. CComQIPtr < IFun > spFun;  // , , NULL 02.
  03. CComQIPtr < IFun > spFun( pOtherInterface );   // , 04. // pOtherInterface QueryInterface() IFun 05.
  06. CComQIPtr < IFun > spFun( spOtherInterface );  // , 07. // spOtherInterface QueryInterface() IFun 08.
  09. CComQIPtr < IFun > spFun ( pUnknown );     // , IUnknown QueryInterface() IFun 10.
  11. CComQIPtr < IFun > spFun = pOtherInterface;    // = , 12. spFun = spOtherInterface;    // 13. spFun = pUnknown;    // 14.
  15. pUnknown->QueryInterface( IID_IFun, &sp );    // QueryInterface 16.
  17. // , 18. if   ( spFun ){}       // 19. if   ( NULL != spFun ){}   // 20.
  21. if   ( !spFun ){}      // 22. if   ( NULL == spFun ){}   //
インテリジェントポインタが関数を呼び出す方法:01. spFun.CoCreateInstance(...);     // API ::CoCreateInstance(...) 02. spFun.QueryInterface(...);   // API ::QueryInterface() 03.
  04. spFun->Add(...);  // 05.
  06. // QueryInterface() , spFun.QueryInterface(...) 07. spFun->QueryInterface(...);  08.
  09. spFun.Release();     // , NULL 10. spFun->Release();     // !!! 。 11. // , ( )
咳……言わないで、言わないで、みんなは多く本を読んで、多くMSNDを见て、多くサンプルのプログラムを见ましょう.书き疲れました:-(
五、まとめ
「COMコンポーネント設計と応用(八)」――ATLコンポーネントの第2のインタフェースを追加する方法に注目してください
注意1:プロキシ/スタブのコンパイル、vc 6.0では少々面倒ですが、「プロセス外コンポーネント」と「リモートコンポーネント」については後述します.vc.net 2003では、プロキシ/スタブが個別のプロジェクトとして自動的にソリューションに追加されるため、簡単です.