1

最初に、私は COM の動作に非常に不慣れですが、他の誰かのために問題をデバッグする任務を負っています。

pvTaskCOM と pvFormsCOM という名前の 2 つの COM プロジェクトがあり、それぞれに多くのインターフェイスがありますが、私が関心を持っているのは次の 2 つです。

pvTaskCOM にある ITaskActPtr

pvFormsCOM にある IChartingObjectPtr

私の問題を引き起こしているコード行は次のとおりです。

ITaskActPtr pTaskAct = m_pChartObj;

m_pChartObj は IChartingObjectPtr です。私が遭遇した問題は、1 つのワークフローでこの割り当てを行った後、pTaskAct が NULL になることでしたが、他のほとんどのワークフローでは問題ありませんでした。デバッガーを使用してここで何が起こっているのかを調べたところ、QueryInterface 中に間違った COM エントリが参照されていることがわかりました。正常に動作するワークフローでは、QueryInterface は pvTaskCOM/pvTaskAct.h からエントリを取得します。

BEGIN_COM_MAP(CTaskAct)
  COM_INTERFACE_ENTRY(ITaskAct)
  .
  .
  .
END_COM_MAP()

キャストしようとしているインターフェイスが含まれており、QueryInterface は S_OK を返します。

しかし、この別のワークフローでは、m_pChartObj は同じ方法でインスタンス化されますが、QueryInterface は何らかの奇妙な理由で pvFormsCOM/ChartingObject.h 内を検索します。

BEGIN_COM_MAP(CChartingObject)
  COM_INTERFACE_ENTRY(IChartingObject)
  .
  .
  .
END_COM_MAP()

これには、キャストしようとしている ITaskAct が含まれていないため、QueryInterface は E_NOINTERFACE を返します。

私が持っている質問は、コードの同じ行に対して 2 つの異なる COM を見ている原因は何ですか? ある種の継承の問題ですか?正しい方向への一歩が必要です。

4

2 に答える 2

2

あなたはおそらく配管で少し迷っています。これは、COM の厳格さを少し緩和するための C++ コードです。COM の重要な側面は、クライアント コードがインターフェイスでのみ動作することです。オブジェクトについては何も知りません。インターフェイスは単純な契約であり、呼び出すことができる関数のリストです。IChartingObject には、たとえば Paint() 関数があります。ITaskAct には、本当の考えではありませんが、「面倒な」何か、Schedule() 関数があります。

m_pChartObj がかなり誤解を招く名前であることに注意してください。オブジェクトではなく、インターフェイス ポインターを格納します。しかし珍しいことではありませんが、オブジェクトが 1 つのインターフェイスのみを実装するか、常に使用する "支配的な" インターフェイスを持っている場合、インターフェイス ポインターをオブジェクト ポインターと考えるのは簡単です。サーバー コード内のオブジェクトを非表示にすることは、COM では非常に強力な目標であり、インターフェイス呼び出しのみを行うことができます。

したがって、ITaskActPtr pTaskAct = m_pChartObj; 基本的に、「私はチャートを持っています。次にタスク関数を呼び出したいです」とアナウンスします。Schedule() と同様です。これには、COM がチャート オブジェクトの実装に「タスク インターフェイス コントラクトについて何か知っていますか?」と尋ねる必要があります。必然的に、IChartingObject の元となった CChartingObject のインターフェイス マップでサーバーに問い合わせて、ITaskAct も実装しているかどうかを確認する必要があります。

したがって、あなたが見ていることは完全に正常です。答えはノーだ"。

于 2017-04-28T21:32:22.933 に答える