2

ThorDetectorSwitch.cpp ファイルのコンストラクターの C++ コードを次に示します。

ThorDetectorSwitch::ThorDetectorSwitch() : _mcSwitch(__uuidof(MCLControlClass))
{
    _A  = WstringToBSTR(L"A"); 
    _B  = WstringToBSTR(L"B");
    _C  = WstringToBSTR(L"C");
    _D  = WstringToBSTR(L"D");

    _deviceDetected = FALSE;
}

ご覧のとおり、初期化リスト は_mcSwitch(__uuidof(MCLControlClass))、COM オブジェクト (COM dll から登録された MCLControlClass) を初期化するために使用されます。

とにかく、この初期化リストの前に CoInitialize() を呼び出すことができるのでしょうか? 「CoInitialize() が呼び出されていません」という例外が発生しているためです。または、この例外を回避する他の方法はありますか?

どうもありがとう。

4

2 に答える 2

4

まず、CoInitializeExの代わりに使用することをお勧めしますCoInitialize。MSDN のドキュメントでさえ、これを推奨しています。次に、COM オブジェクトの使用を必要とする追加の各スレッドの開始時に呼び出しを行うことをお勧めしますCoInitializeExmain()これには非常に正当な理由があります。たとえば、各呼び出しには、スレッドが終了CoInitializeExする前に対応する呼び出しが必要です。CoUninitializeこれにより、COM ライブラリが適切に終了されます。コンストラクターから呼び出す場合は、適切な数の呼び出しCoUninitializeが行われるように、COM ライブラリが初期化される回数も管理する必要があります。別の問題は、後続の呼び出しがCoInitializeEx別のアパートメント モデルで行われたときに失敗することです。これが発生し、コンストラクターが本来あるべきエラーをチェックしている場合インスタンス化中に失敗状態になります。コンストラクターでそのようなエラー状態をどのように処理しますか? 例外をスローすることによって - 発生するのはあまり楽しいことではありません。

私の最後の推奨事項は、ドキュメントを読んで正しい方法で物事を行うことです。そうしないと、ここ数日間のように頭を悩ませることになります。

于 2013-06-14T04:48:00.067 に答える
1

このような init を main() または InitInstance やその他の改良に任せることを提案する人たちには同意しますが、元の質問に対する 1 つの解決策を示しましょう。

関数を呼び出すと責任が生じるため、次のような RAII ラッパーから始めます。

class ComIniter
{
public:
    ComIniter() { CoInitialize(); } // or use ex, add params, etc
    ~ComIniter() { CoUnInitialize(); } // adjust to match
private:
    ComIniter(const ComIniter&);  // =delete with C++11
    ComIniter& opeartor=(const ComIniter&); // =delete with C++11
};

COM を必要とする他の静的オブジェクトの前に、main()、スレッド関数、および/または名前空間スコープの開始時にインスタンスを削除できます。

それらに反対して元のアイデアが必要な場合は、ThorDetectorSwitch に以下を追加します。

private: static const char* ComHelper(const char* arg) { static ComIniter c; return arg; }

次に、init リストで使用します。

ThorDetectorSwitch::ThorDetectorSwitch() : _mcSwitch(ComHelper(__uuidof(MCLControlClass)))

必要に応じて戻り値の型を調整してください。繰り返しになりますが、これは他のソリューションと比較して次善のソリューションと見なされています。

于 2013-06-14T08:11:42.333 に答える