COM難しいよー(T T) (2)&(3)

昨日の「COM難しいよー」問題。

うまくいかない原因は判明しました。
そう、うまくいかない原因

成功したテスト用と今作ってるやつと何が違うのか、色々比べてみたら「プロジェクトの種類」が違っていることに今さらながら気づいたわけです。

で、

成功してたのが Win32コンソールプロジェクト
失敗してたのが、MFCプロジェクト

どうやらMFCにはMFCのCOMの実装手順があるみたいです。
細かく言うと、接続ポイントとか、DISPインターフェースをマップしたり他にも何かしなくちゃいけないかもだけど、今日はここで力尽きた...

MFC特有の実装というものはありませんでした。もう一度、シンプルなテスト用のイベントシンクをMFC上で走らせてみたら普通に動いた。

こうなったら確実にできそう&検索でもひっかかりそうな ATLを使ってみようかなと思ったりしてますが、どうなんでしょうね。
危うく、未開拓地であるATLに手を出す所でした...危ない危ない。COMも十分オーバーテクノロジーだったんですが、今回の件で接続ポイント回りには詳しくなれたぞと。

解決はまだしてない。けど

どれが原因か特定できなかったから色々な方向から調べてCOMについてちょっと詳しくなった。仕事は進んで無いけど、経験値は確実に溜まっていってるはず!!

そう考えないとやってけないよ。…だってこの1週間、この問題に掛かりっきりだったし。(T^T)

とにかく、解決するまで色んなアプローチを続けてみます!

というわけで解決しました。

これが原因だった!と1つに絞りきれなかったので、
思い当たる原因を列挙。

  • importしたタイプライブラリと実行時に読み込むDLLの整合が取れていなかった?
  • ソースオブジェクト側のevent変数名と、ソースインターフェイスのメソッド名が違っていた?
  • CoCreateInstanceでコンポーネントを作成してから、FindConnectionPointまでの呼び出し方がまずかった?

最後におさらい

今回のC#でイベントソースオブジェクト、C++でイベントシンクオブジェクトを作る手順を忘れないようにメモ。

C#側(イベントソース)

[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] ←属性に追加

[ComSourceInterfaces(typeof(/*イベントソースインターフェイス名*/))]←属性に追加

中間作業(タイプライブラリの作成)
  • RegAsm.exeを使ってC#で作ったDLLからTLBファイルを出力する
C++側(イベントシンク)
  • タイプライブラリをimport

#import "****.tlb" raw_interfaces_only named_guids

あとはCOMの流儀に従って、、、

  • コンポーネントをCoCreateInstance()
  • IConnectionPointContainerをQueryInterface()
  • IConnectionPointをFindConnectionPoint()
  • 取得したIConnectionPointをAdvise

そして、イベントシンクが必要なくなったら

  • 取得したIConnectionPointをUnadvise

参考文献

  • COMのイロハを教えてくれた本「Inside COM」(が、絶版らしいです。奇跡的に会社にあってラッキー!)
  • 接続ポイントが詳しく書かれていた本「Inside DCOM」(分かり易かった)