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にすると、 */
           /* ここで無効なポインターエラーが発生 */