- ベストアンサー
DirectShow Filterのinterface定義でエラーが発生する原因を解析
- DirectShow Filterのinterface定義で呼び出し規約のエラーが発生する
- DirectShowのGraphEdit上で動作する自作Filterを作成したが、C++プログラム上で独自定義のメソッドを呼び出すとエラーが発生
- DEFINE_GUIDやMIDL_INTERFACEを使用してクラスとインターフェースを定義し、__stdcallを指定しているが、呼び出し元と先で呼び出し規約が異なるというエラーが出てしまう
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
こんばんは。補足頂きました。 原因は「ダウンキャストが不完全であった」と言う事の様です。 多重継承になっている為、IMyClass*ではなく、最下層のCMyClass*へダウンキャストしてから、IMyClass*へアップキャストします(クロスキャスト)。 当方のVC2005では、以下で動作しました。参考程度に。 //以下を修正 HRESULT CMyClass::NonDelegatingQueryInterface(REFIID riid, void **ppv) { CheckPointer(ppv,E_POINTER); if ( riid == IID_IMyClass ) { //クロスキャスト IMyClass* pLeft = static_cast<CMyClass*>(this); return GetInterface(pLeft, ppv); } else { return CTransInPlaceFilter::NonDelegatingQueryInterface(riid, ppv); } } //以下で実行 int main() { ::CoInitialize(NULL); IMyClass* pMyClass; ::CoCreateInstance(CLSID_MyClass, NULL, CLSCTX_INPROC, IID_IMyClass, (LPVOID*)&pMyClass); pMyClass->myMethod(); pMyClass->Release(); ::CoUninitialize(); return 0; }
その他の回答 (3)
- machongola
- ベストアンサー率60% (434/720)
こんにちは。御礼頂きました。 もう一度試しましたが、確かにreinterpret_cast<>の時におかしくなっています。 よくよく考えれば、thisはCMyClass*constでした。 「当方がクロスキャストしていないと勘違いして元凶であるreinterpret_cast<>を止めた」から動作したと言う事なので、クロスキャスト自体は関係ありませんでした。 当方はクラスのキャストにreinterpret_cast<>を使った事が無いので、此の事例は初めて見ました。 肝心な「クラスのキャストにreinterpret_cast<>を使用すると何故おかしくなるのか」に関して、当方はC++の規格には詳しくない為、これ以上明言する訳にはいかないので、大変申し訳ありませんが、此処でギブアップと言う事になります。
補足
各キャストが返す値を観察してみましたがどのキャストも同じ値を返してますね。 結局原因はよく分かりませんが当初の問題は解決しているので これで締めきらせていただきます。 回答していただいた皆様、ありがとうざいました。
- machongola
- ベストアンサー率60% (434/720)
こんにちは。 上手く行かないかもしれませんが、NonDelegatingQueryInterface()をオーバーライドしても駄目でしょうか。 IMyClass : public IUnknown { STDMETHOD(myMethod)(void) PURE; }; class AM_NOVTABLE CMyClass : public CTransInPlaceFilter, public IMyClass { CMyClass ::CMyClass (IUnknown * pOuter, HRESULT * phr, BOOL ModifiesData); CMyClass ::~CMyClass (); public: static CUnknown *WINAPI CMyClass::CreateInstance(LPUNKNOWN punk, HRESULT *phr); DECLARE_IUNKNOWN; STDMETHODIMP CMyClass::myMethod(void){return S_OK;} //from CBaseFilter [amfilter.h/cpp] STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv) { //独自のインターフェースなら if(riid == IID_IMyClass) { return GetInterface((IMyClass *)this, ppv); } //其れ以外なら return CBaseFilter::NonDelegatingQueryInterface(riid, ppv); } }
補足
説明のためにコードを簡略化したので色々抜けてますね; 実際はNonDelegating~も実装してますが開発中のコードは載せられないので 検証用にCTransInPlaceFilterを派生させてmyMethod()だけ追加したコードを 作りました。 (名前はMyFilterの方が良かったな…) http://www.rupan.net/uploader/download/1251359357.zip pass:1234(ウィルスバスターでスキャンしてますが自己責任でお願いします) 今度はデバッグすると pMyClass->myMethod(); を抜けるとデストラクタに入り例外が発生してしまいます。 メモリアクセス違反が起こってるようですが 何が起こっているのか余計に分からなくなってきました…。
- chie65536(@chie65535)
- ベストアンサー率44% (8741/19839)
当てずっぽで不確かな回答で申し訳ありません。 #暫くC++から離れていたので忘れかけてます >pMyClass->myMethod();←ここでエラー ドット演算子とアロー演算子の使い分けを再確認してみて下さい。
補足
宣言部の写しミスです、申し訳ありません;; 誤)IMyClass pMyClass; 正)IMyClass *pMyClass; です。
お礼
提示して頂いたコードに書き直すことで 動作するようになりました。本当にありがとうございます。 今までCしか触ってなかったので C++特有のキャストの事などよく知りませんでした。 クロスキャストについて少し調べたのですが納得できていないことがあるので もう一点質問させてください。 thisポインタはこの場合CMyClass *const型ですよね? すると「CMyClass *const」→「CMyClass *」→「IMyClass *」 とキャストしているように見えるのですが それって「CMyClass *const」→「IMyClass *」と直接アップキャストしても問題ないような気がします。 実際 return GetInterface(static_cast<IMyClass*>(this), ppv); や return GetInterface(dynamic_cast<IMyClass*>(this), ppv); や return GetInterface((IMyClass*)this, ppv); と書いてもエラーは起きなくなります。 すると問題になっていたのはreinterpret_castか?と考えます。 各C++独自キャストの説明を見ると static_castとdynamic_castはチェック機構を除けば 行っていることは(IMyClass*)thisのCスタイルのキャストと同じに見えます。 このキャストは暗黙的にビットパターンが変更されているようです。 これに対しreinterpret_castは http://msdn.microsoft.com/ja-jp/library/cc440192(VS.71).aspx (保証はないが)ビットパターンを変更せずに再解釈する、とあります。 つまり無理やりな代入を行っただけで正しくキャストできておらず今回のエラーに繋がった、ということではないでしょうか?