読者です 読者をやめる 読者になる 読者になる

echo("備忘録");

IT技術やプログラミング関連など、技術系の事を備忘録的にまとめています。

C#でCOMを使ってみた。その2

.net Windows

どうしても今月中に役所へ行かなければならないので、申し訳ないと思いながらも12日に休暇申請したら「正直、よくそんな面の厚いことが出来るな、という感じだけどね」みたいな事を言われた。
バイ、これは早急に身の振り方を考えないと。


…というわけで、その1の続きです。


COMインターフェースのインスタンス作成・キャスト

「コクラスが持つインターフェースにアクセスする」場合や「定義したCOMインターフェースと互換性がある」場合は、メソッドなどを実行しなくても、キャストを実行するだけでCOMインターフェースのインスタンスを作成できます。

DirectSoundCapture8Class DSC = new DirectSoundCapture8Class();
IDirectSoundCapture8 iDSC = (IDirectSoundCapture8)DSC;

ただキャストするだけではエラーになる場合は(ネイティブ側のCOMインターフェースポインタを受け取る場合など)、MarshalクラスのGetTypedObjectForIUnknown()メソッドの戻り値をキャストすればOKです。(これを発見するのにすごく時間がかかった…)

public static object GetTypedObjectForIUnknown(
  IntPtr pUnk,    // ネイティブ側のCOMインターフェースポインタ
  Type t          // (COMインターフェースなどの)型
)


// ptr_iDSCB8にネイティブ側のCOMインターフェースポインタが格納されているものとする。
IDirectSoundCaptureBuffer8 iDSCB8 = (IDirectSoundCaptureBuffer8)Marshal.GetTypedObjectForIUnknown(ptr_iDSCB8, typeof(IDirectSoundCaptureBuffer8));


ネイティブ側のCOMインターフェースポインタの取得

ネイティブ側のCOMインターフェースポインタ取得ですが、

1.MarshalクラスのQueryInterface()メソッドを使う方法
C++での方法ですね。

public static int QueryInterface(
    IntPtr pUnk,    // 取得したいCOMインターフェースの取得をサポートしているCOMインターフェースのポインタ
    ref Guid iid,   // 取得したいCOMインターフェースのIID
    out IntPtr ppv  // 取得したいCOMインターフェースのポインタが格納される
)


// ptr_iDSCB8にIDirectSoundCaptureBuffer8インターフェースポインタが入っていて、
// 取得したIDirectSoundNotify8インターフェースポインタをptr_iDSN8に格納したい場合。
// guidにはIDirectSoundNotify8インターフェースポインタのIIDが格納されているものとする。
int getNotifyResult = Marshal.QueryInterface(ptr_iDSCB8, ref guid, out ptr_iDSN8);
IDirectSoundNotify8 iDSN8 = (IDirectSoundNotify8)Marshal.GetTypedObjectForIUnknown(ptr_iDSN8, typeof(IDirectSoundNotify8));


2.普通にインターフェースポインタを取得できるネイティブ側のメソッドを使用する。

// (例)DirectSoundのDirectSoundCaptureCreate8()メソッドを呼び出した場合。
// guidにIDirectSoundCapture8インターフェースのIIDを渡すと、正しく処理が行われた場合、ptr_iDSC8に
// IDirectSoundCapture8インターフェースポインタが格納される。(第三引数はnull固定。)
int createCaptureResult = DirectSoundCaptureCreate8(ref guid, out ptr_iDSC8, null);
IDirectSoundCapture8 iDSC8 = (IDirectSoundCapture8)Marshal.GetTypedObjectForIUnknown(ptr_iDSC8, typeof(IDirectSoundCapture8));

う~ん、ざっと説明してきましたが、分かりにくい内容になってしまったような…申し訳ないです。


【追記】
冒頭の件、別に「5連休にしたい!」とかそういう意図ではなく「(どうせ有休で休む人が多いんだし、他の人にあわせて)休むときは休む、働くときは働く」っていう考えだったからこの日にしたんだけど…
それを「面の皮が厚い」とか「他の日にしない理由が見つからない」とか言われるのであれば、真剣に考えないとねえ。