TStreamAdapterをIStreamに変換する
どのバージョンから変わったかもう覚えていないが、C++ BuilderでVCLベース(Delphiクラスオブジェクト)のポインターを扱う場合、場合によっては通常のC++のポインターではだめな場合がでるようになった。
例えばTXMLDocumentでノードの取り扱いがそうで、TXMLNode*ではなく_di_XMLNodeを使わなくてはならない。
タイトルのTStreamAdapterも実はそのパターンだ。
TMemoryStream* pMS = new TMemoryStream; TStreamAdapter* pSA = new TStreamAdapter( pMS, soReference ); IStream* p = *pSA; /* 昔はこれで変換できた。 今はエラーが発生 */ _di_IStream p = *pSA; /* 今はこう書く */
TStreamAdapterの扱いは注意が必要だ。下の例ではGDI+のBitmapをストリームに書き出ししているコードだが、TStreamAdapoterオブジェクトをdeleteするとエラーが発生する。
また、soOwnedパラメータをつけて生成すると、ストリームの削除でエラーが発生する。
bool save_to_stream( Gdiplus::Bitmap* bmp, TMemoryStream* ms, CLSID ci ) { TStreamAdapter* pSA = new TStreamAdapter( ms, soReference ); _di_IStream p = *pSA; Gdiplus::Status stat = bmp->Save( p, &ci ); delete pSA; /* ここでエラーが発生。 削除コードは無しで良い模様 */ return ( stat == Gdiplus::Ok ); } /* 呼び出し元 */ TMemoryStream* ms = new TMemoryStream; save_to_stream( bmp, ms, ci ); /*~ストリームを使って作業*/ delete ms; /* soReferenceをsoOwnedにすると、 */ /* ここで無効なポインターエラーが発生 */