C++/CLI ラッピング入門4 メンバ変数の公開 クラス・構造体編

C++/CLI ラッピング入門4
今回はラップしたアンマネージドクラスの
クラス、構造体などの複合型メンバ変数をマネージ側に公開します。
—————————————————————–

・クラス・構造体型メンバ変数の公開

アンマネージドクラスclassAの、classB型(アンマネージ)のメンバ変数BをC++/CLIでマネージド側に公開する場合

内部では、classAと、そのメンバ変数B(classB)のつながりを保ったまま、
外からは、classAのラッパークラス A_Wrapperが
classBのラッバークラスB_Wrapper型のメンバ変数Bを持っているようにみえるのが望ましいです。


図1 内部ではclassAとclassBはつながっていて、その結合を保ったまま、ラップする
 
 

図2 外からは、A_WrapperがB_Wrapperをメンバに持っているように見えるようにする

そこで、B_WrapperにはclassBのポインタを受け取るのコンストラクタを作成し、
A_Wrapperでは、B_Wrapper型のプロパティBを公開し、
その内部では、
classAのメンバ変数B(classB型)を先ほど作成したポインタを受け取るコンストラクタにわたして、B_Wrapperオブジェクトを作成するようにします。

//---------------------
// アンマネージドクラス定義  (C++)
namespace CPP
{
  class classB
  {
    public:
       //classBコンストラクタ
      classB():i(0){}

      //メンバ変数
	  int i;
  };

  class classA
  {
    public:
      // コンストラクタ
      classA(){} 

      // メンバ変数B
      classB B;
  };

}
//---------------------
// マネージドラッパー (C++/CLI)
namespace CLI
{
  // classBのラッパー
  public ref class B_Wrapper
  {
    public:
    // B_Wrapperを単体で作る時用のコンストラクタ
    B_Wrapper(){pB = new CPP::classB();}

    ~B_Wrapper(){this->!B_Wrapper();} //デストラクタ
    !B_Wrapper(){delete pB;} //ファイナライザ

    // classBのメンバ変数を公開
    property int i
    {
        int get()
        { return pB->i; }
        
        void set(int value)
        { pB->i = value; }
    }

    internal:
      CPP::classB* pB;

      //メンバ変数としての公開用のコンストラクタ
      // アセンブリの外からは呼び出さないのでinternal
      B_Wrapper(CPP::classB* ptr)
      {
         pB = ptr;
      }
  };

  // classAのラッパー
  public ref class A_Wrapper
  {
    public:
      A_Wrapper(){pA = new CPP::classA();}
      ~A_Wrapper(){this->!A_Wrapper();}
      !A_Wrapper(){delete pA; }

     //classAのメンバ変数bをプロパティでラップして公開
      property B_Wrapper^ B
      {
        //classBをB_Wrapperとして公開
        B_Wrapper^ get()
        { return gcnew B_Wrapper(&(pA->B)); }
        
        //B_Wrapper内のclassBオブジェクトをコピー
        void set(B_Wrapper^ value )
        { pA->B = *value->pB; }
      }

    internal:
      CPP::classA* pA;
    };
}
//----------------------------

しかし、このままでは、newで直接確保したわけではない
B_Wrapperに格納されているclassBへのポインタ(classAオブジェクトのメンバ変数B)に対してもdeleteが実行されてしまいます。

コレを防ぐために
ポインタを受け取るコンストラクタでフラグを建てて、
このフラグが立っている場合はdeleteされないようにします。

//---------------------
// B_Wrapper delete防止
  public ref class B_Wrapper
  {
    public:
    // B_Wrapperを単体で作る時用のコンストラクタ
    B_Wrapper():no_alloc_flag_(false)
    {pB = new CPP::classB();}
    
    ~B_Wrapper(){this->!B_Wrapper();} //デストラクタ
    !B_Wrapper()
    {
       // ポインタを受け取るコンストラクタで立てられるフラグが立っていれば、
       //deleteしない
       if(!no_alloc_flag_)
       {delete pB;}
    } //ファイナライザ

    // classBのメンバ変数を公開
    property int i
    {
        int get(){return pB->i;}
        void set(int value){pB->i = value;}
    }

    internal:
      CPP::classB* pB;
     //delete防止ようフラグ
      bool no_alloc_flag_;
      //メンバ変数としての公開用のコンストラクタ

      // アセンブリの外からは呼び出さないのでinternal 
      B_Wrapper(CPP::classB* ptr):
            no_alloc_flag_(true) // deleteしないようにフラグを立てる
      {
         pB = ptr;
      }
  };

akatukisiden について

フリーランスプログラマ 使用言語はC++,C#とそのつなぎのC++/CLI 専門はクライアントアプリ開発
カテゴリー: C++/CLI, 相互運用 パーマリンク

コメントを残す