2016-07-25 2 views
1

私は以下のCOMタイプを持っています:Project,ContainerItemおよびNodeです。 Projectには、ContainerItemを受け入れるAppend関数を持つコレクションプロパティがあります。 C#のでC++でのCOMタイプのキャスト

は、タイプライブラリを使用して、私は予想通りAppend機能とライブラリの作品にNodeオブジェクトを送信することができます

var prj = new Project(); 
var node = new Node(); 
prj.collection.Append(node); 

は、C++では、私はこれはC#は何をしていたかで期待して、直接ポインタのキャストを試してみました、しかし、それはエラーで終わる:

ProjectPtr prj; 
prj.CreateInstance(__uuidof(Project)); 
NodePtr node; 
node.CreateInstance(__uuidof(Node)); 
prj->collection->Append((ContainerItem**)&node.GetInterfacePtr()); 

これらのタイプのCOMポインタキャストは、C++で具体的な方法がありますか?私は何が欠けていますか? @HansPassantは、コメントと同じように

+2

CスタイルのキャストはCOMインターフェイスでは有効ではないため、QueryInterface()を使用する必要があります。 C#は自動的にそれを行いますが、C++でそれを自分で行う必要があります。 –

+0

'Append'が' ContainerItem ** 'をパラメータとしてとることはほとんどありません。それは意味をなさないでしょう。 'Append'の宣言は何ですか? 'Node'と' ContainerItem'の関係は何ですか? –

+0

@IgorTandetnik定義はContainer :: Append(ContainerItem **、long *)です.2番目のパラメータは途中でnullになることがあります。コンパイラがCOM DLLから作成する.tliファイルには表現されていないため、NodeとContainerItemの関係はわかりません。 – tunc

答えて

1

COMキャストはQueryInterface()方法で行われます。オブジェクトはGUIDに基づいてインターフェイスをサポートするかどうかを問い合わせられ、インターフェイスがサポートされている場合は内部参照カウンタがインクリメントされ(AddRef()参照)、インターフェイスへのポインタが返されます。 MSDN has more detail on the inner workings

C++は「COMキャスト」のコード生成を直接サポートしていませんが、実装は簡単です。

struct bad_com_cast : std::runtime_error { 
    bad_com_cast() : std::runtime_error("COM interface not supported") {} 
}; 

template <class To, class From> 
To* qi_cast(From* iunknown) 
{ 
    HRESULT hr = S_OK; 
    To* ptr = NULL; 
    if (iunknown) { 
     hr = iunknown->QueryInterface(__uuidof(To), (void**)(&ptr)); 
     if (hr != S_OK) { 
      throw bad_com_cast(); // or return NULL 
     } 
    } 
    return ptr; 
} 

上記のキャストを使用すると、サンプルは次のように実装できます。 ATLライブラリが使用されている場合

ContainerItem* ci = qi_cast<ContainerItem>(node); 
prj->collection->Append(&ci); 

、あなたは同等の意味を得るために、直接ATL::CComQIPtr<>を使用することができます。

auto ci = CComQIPtr<ContainerItem>(node); 
if (ci) { 
    // ... 
} 
0

、私はQueryInterface関数を使用する必要がありました:

ContainerItem* ci = nullptr; 
node.QueryInterface(__uuidof(ContainerItem), ci); 
prj->collection->Append(&ci); 
関連する問題