狠狠撸

狠狠撸Share a Scribd company logo
C++/CLI
ネイティブライブラリラッピン
     グ入門


     暁 紫電


    わんくま同盟 東京勉強会 #69
自己紹介
? HN 暁 紫電
? Twitter @akatukisiden
? 年齢 25歳
? フリープログラマー
? 使用言語
    C++、C++/CLI、C#
? 現在のお仕事
    Kinect(OpenNI)、OpenCV、MIDI

         わんくま同盟 東京勉強会 #69
マネージ コードとネイティブ コード
    相互運用テクノロジ

? P/Invoke
? COM
? C++/CLI



        わんくま同盟 東京勉強会 #69
Platform Invoke (P/Invoke)
? DLLからC スタイルのネイティブ関数を呼び出す。
? ヘッダファイルの情報を
           .NET側に用意する必要がある。
? .NET Frameworkの内部でよく使用されている
? 引数のマネージ←→ネイティブ変換コストに加
  え
    一回の呼び出しでx86命令10~30個分の
    オーバーヘッドが係る
? どんな関数でも正常に呼び出せるわけではない


           わんくま同盟 東京勉強会 #69
COM相互運用
? I Unknown
? マネージ コードからCOMインターフェイスを使
  用、
   またはマネージAPIを COMインターフェイス
として
   公開する機能
? Office関連や、WinRTなどで使われている
? 時間コストはC++/CLIと同程度


              わんくま同盟 東京勉強会 #69
C++/CLI
? Cヰ
? マネージ コードおよびネイティブ コード
  が混在するアセンブリを作成する
? P/Invokeとは違い、見た目は普通の
  マネージオブジェクトにすることが可能
? おそらく、どんなクラス?関数でもラップ
  可能



       わんくま同盟 東京勉強会 #69
今回は
画像処理ライブラリOpenCVのラップを通し
             て
       C++/CLIを用いた
.NETでのネイティブコードの利用について
        紹介します。
※ ヘッダファイルに宣言と定義、両方まとめて書いてい
     ますが、実際は分けて書いてください



         わんくま同盟 東京勉強会 #69
マネージ型

  値?参照\デフォ
      ルト        Public          private
   アクセス指定子

    参照型        ref struct;     ref class;


    値型        value struct;   value class;



? class structの使い方はC++相当
? 値型?参照型はその前につけるvalue/refで決ま
  る。
? 参照型のハンドルは型名の後ろに^をつけて表
  す
             わんくま同盟 東京勉強会 #69
矩形等のサイズを表す構造体
  CvSizeをラップする




    わんくま同盟 東京勉強会 #69
Wrap1 最低限のラップ (CvSize)
public ref class CvSize
{
    public:
        CvSize(void)
        { ptr = new ::CvSize; }

         ~CvSize()
         { this -> !CvSize(); }

         !CvSize()
         { delete ptr; }
     internal:
         ::CvSize* ptr;
};



                  わんくま同盟 東京勉強会 #69
Wrap1 最低限のラップ (CvSize)
? ref class
? ネイティブオブジェクトのポインタを
            internalメンバとして持たせる。
? コンストラクタでオブジェクトを生成
? デストラクタ/ファイナライザで破棄
? デストラクタ(~Class())はDispose(true)相当
? ファイナライザ(!Class())はDispose(false) 相当
? ファイナライザは通常の関数として呼び出し可
  能


             わんくま同盟 東京勉強会 #69
Wrap2 基本型メンバ変数の公開 (CvSize)
public ref class CvSize
{
    // ~~略~~
    public:
         property int width
         {
             int get(){ return ptr_->width;}
             void set( int value ){ ptr_->width = value; }
         }
         property int height
       {
             int get(){return ptr_->height;}
            void set(int value){ptr_->height = value; }
         }
    internal:
         ::CvSize* ptr_
};


                         わんくま同盟 東京勉強会 #69
Wrap2 基本型メンバ変数の公開 (CvSize)

? メンバ変数はプロパティとして公開する
? Internalポインタを通してメンバ変数にアクセス
? 基本型はマネージ、ネイティブ間で互換性有り




          わんくま同盟 東京勉強会 #69
OpenCV画像クラス
IplImageをラップする




   わんくま同盟 東京勉強会 #69
Wrap3 ポインタで管理するクラス
                       (IplImage)
public ref class IplImage
{
    public:
      IplImage(CvSize^ size,int depth,int channels)
      { ptr = ::cvCreateImage(*size->ptr,depth,channels);}

      ~IplImage(){ this->!IplImage(); }

      !IplImage()
      {
          pin_ptr<::IplImage*> pin_Image = &ptr;
          ::cvReleaseImage(pin_Image);
      }
      internal:
          ::IplImage* ptr;
};


                      わんくま同盟 東京勉強会 #69
Wrap3 ポインタで管理するクラス
          (IplImage)
? 独自の生成関数、解放関数を持ち、
  インスタンスはポインタで管理するクラス
? 生成?解放関数自体はコンストラクタ、
      ファイナライザ内で呼び出す。
? ダブルポインタを引数に取る関数(解放関数)は
  そのままではガベコレでアドレスが変わる
  可能性があるというエラーが発生するので
  pin_ptr<T*>でアドレスを固定する



        わんくま同盟 東京勉強会 #69
画像ファイル読み込み関数
    cvLoadImageを
コンストラクタとしてラップ




     わんくま同盟 東京勉強会 #69
Wrap4 文字列変換(cvLoadImage)
public ref class IplImage
{
  // ~~略~~
  public:
    IplImage(System::String^ str, int iscolor)
    {
          const char* chars = (const char*)
                 System::Runtime::InteropServices::Marshal
                               ::StringToHGlobalAnsi(str).ToPo
inter();

               this->ptr = ::cvLoadImage(chars ,iscolor);

               System::Runtime::InteropServices::Marshal
                                ::FreeHGlobal(System::IntPtr((vo
id*)chars));
    }
// ~~略~~
};
                        わんくま同盟 東京勉強会 #69
Wrap4 文字列変換(cvLoadImage)
? System.Stringからchar*に変換
? マネージ?アンマネージの変換用の関数をまと
  めたMarshalクラスのメンバを使用
? IntPtr Marshal::StringToHGlobalAnsi(string);
     String の内容をアンマネージ メモリにコピーし、
     コピー時に ANSI 形式に変換します。
? void Marshal::FreeHGlobal(IntPtr);
     アンマネージメモリから割り当てられたメモリを
     解放します。



                 わんくま同盟 東京勉強会 #69
しきい値処理関数
cvThresholdをラップする




    わんくま同盟 東京勉強会 #69
Wrap5 関数のラップ(cvThreshold)
public ref class IplImage
{
 // ~~略~~
    double cvThreshold( IplImage^ src, IplImage^ dst,
        double threshold, double max_value, int
threshold_type )
    {
        return ::cvThreshold(src->ptr, dst->ptr,
                         threshold, max_value,
threshold_type);
    }
};




                   わんくま同盟 東京勉強会 #69
Wrap5 関数のラップ(cvThreshold)
? オブジェクトを引数に取るものは
   内部ポインタを(必要なら*をつけて)渡す。
? 基本型引数はそのまま渡せる。




          わんくま同盟 東京勉強会 #69
とりあえず一回実行してみる




 ※ 表示に必要な関数は予めラップ済
 み




       わんくま同盟 東京勉強会 #69
表示用関数郡
using namespace System::Runtime::InteropServices;
public ref class GUI
{
  public:
    static int cvNamedWindow( System::String^ str, int flags )
    {
      const char* chars = (const char*)
                     Marshal::StringToHGlobalAnsi(str).ToPointer();
      int r = ::cvNamedWindow(chars,flags);
      Marshal::FreeHGlobal(System::IntPtr((void*)chars));

        return r;
    }




                        わんくま同盟 東京勉強会 #69
表示用関数
     static void cvDestroyWindow( System::String^ str)
     {
       const char* chars = (const char*)
              Marshal::StringToHGlobalAnsi(str).ToPointer();
       ::cvDestroyWindow( chars );
       Marshal::FreeHGlobal( System::IntPtr((void*)chars));
     }

     static void cvShowImage( System::String^ name,IplImage^ image)
     {
         const char* chars = (const char*)
                     Marshal::StringToHGlobalAnsi(name).ToPointer();
         ::cvShowImage( chars ,image->ptr);
         Marshal::FreeHGlobal( System::IntPtr((void*)chars));
       }
       static int cvWaitKey(int delay)
       { return ::cvWaitKey(delay); }
};

                       わんくま同盟 東京勉強会 #69
実行コード C#

class Program
{
    static void Main( string[] args)
    {
        GUI.cvNamedWindow( "window" , 1);

       IplImage loadedImage = new IplImage( "wankuma.png” , 0);

       GUI.cvShowImage( "window” , loadedImage);
       GUI.cvWaitKey(0);

       CvSize size = new CvSize();
       size.width = loadedImage.width;
       size.height = loadedImage.height;
       IplImage img2 = new IplImage(size, loadedImage.depth,
                                          loadedImage.nChannels );



                        わんくま同盟 東京勉強会 #69
実行コード C#

        IplImage.cvThreshold(loadedImage, img2, 205, 255, 0);

        GUI.cvShowImage( "window" , img2);
        GUI.cvWaitKey(0);

        GUI.cvDestroyWindow( "window"   );
    }
}




                        わんくま同盟 東京勉強会 #69
わんくま同盟 東京勉強会 #69
わんくま同盟 東京勉強会 #69
わんくま同盟 東京勉強会 #69
二値画像から輪郭と
その外接矩形を取得する




   わんくま同盟 東京勉強会 #69
Wrap6
 輪郭クラスはメモリストレージ
CvMemStorage内に確保されるので
  まずはCvMemStorageをラップ



       わんくま同盟 東京勉強会 #69
Wrap6 メモリストレージ CvMemStorage
public ref class CvMemStorage
{
    public:
        CvMemStorage( int block_size)
        { ptr_ = ::cvCreateMemStorage(block_size);   }

        ~CvMemStorage() { this->!CvMemStorage();}

       !CvMemStorage()
        {
            pin_ptr< ::CvMemStorage* > p = &(this->ptr_ );
            ::cvReleaseMemStorage( p ) ;
        }
        static void cvClearMemStorage(CvMemStorage^ storage)
        { ::cvClearMemStorage(storage->ptr_ ); }

     internal:
         ::CvMemStorage* ptr_;
};

                          わんくま同盟 東京勉強会 #69
Wrap6 メモリストレージ CvMemStorage

? コンストラクタでストレージ生成
? ファイナライザで全解放
? 割り当て済みストレージの解放関数
 – void cvClearMemStorage(CvMemStorage^ storage);




                わんくま同盟 東京勉強会 #69
wrap7
輪郭クラスCvContourは生成?破棄の方法が
         特殊なので
先にそのメンバ変数rect(CvRect型)をラップ
             し
    プロパティとして公開する




         わんくま同盟 東京勉強会 #69
Wrap7 複合型メンバ変数をプロパティとして公開
           (CvContour::rect)




Class AとそのメンバBをラップしたものが

         わんくま同盟 東京勉強会 #69
Wrap7 複合型メンバ変数をプロパティとして公開
           (CvContour::rect)




ClassAのラッパーがBのラッパーをメンバに持つよ
うに見えるようにする必要がある

          わんくま同盟 東京勉強会 #69
Wrap7 複合型メンバ変数をプロパティとして公開
               (CvContour::rect)
public ref class CvContour
{
   public:
     // ~~略~~
     property CvRect^ rect
     {
       CvRect^ get()
       {
         return gcnew CvRect(&ptr_->rect);
       }
       void set(CvRect^ value)
       {
           *ptr_->rect = *(value->ptr_);
       }
     }
     internal:
         ::CvContour* ptr_;
};

                         わんくま同盟 東京勉強会 #69
Wrap7 複合型メンバ変数をプロパティとして公開
                (CvContour::rect)
public ref class CvRect                   ~CvRect()
{                                         { this->!CvRect();}
  public:
    // ~~略~~                              !CvRect()
    CvRect()                              {
    {                                        if(!noalloc_)
      noalloc_ = false;                      {
      this-> ptr_ = new ::CvRect;              delete ptr_;
    }                                        }
                                             this->ptr_ = nullptr;
   CvRect( ::CvRect* pRect)               }
   {                                    private:
     noalloc_ = true;                      bool noalloc_ ;
     this->ptr_ = pRect;
   }                                    Internal:
                                           ::CvRect* ptr_;
                                    }


                         わんくま同盟 東京勉強会 #69
Wrap7 複合型メンバ変数をプロパティとして公開
            (CvContour::rect)
? プロパティのgetterではポインタを受け取
  るコンストラクタを用いて、
  ラッパーオブジェクトを作成(gcnew)する。
? ポインタを受け取るコンストラクタで初期
  化した場合は非破壊フラグを立て、ファイ
  ナライザでdeleteしないようにする。
? setterではvalue側の内部ポインタの指す値
  をコピーする。


          わんくま同盟 東京勉強会 #69
wrap8
輪郭スキャンクラス
 CvContourScanner
輪郭スキャン関数群
cvStartFindContours
 cvFindNextContour
cvEndFindContours
      のラップ


    わんくま同盟 東京勉強会 #69
Wrap8 輪郭スキャン関連




     使い方が複雑なので
まずC++側でどのように使うかを確認




      わんくま同盟 東京勉強会 #69
Wrap8 輪郭スキャン関連(C++)
IplImage img_th = 閾値処理後の画像
CvContourScanner scanner = cvStartFindContours(img_th, storage);

CvContour* contour;
do
{
    contour = reinterpret_cast< CvContour*>
                            ( cvFindNextContour(scanner) );
    if(contour != nullptr)
    {
      CvRect rect = contour->rect;
    }
}
while (contour != nullptr);
contour = reinterpret_cast<CvContour*>(cvEndFindContours(&scanner));
cvClearMemStorage(contour->storage);



                         わんくま同盟 東京勉強会 #69
Wrap8 輪郭スキャン関連(C++)
? CvContourScanner は_CvContourScanner*のtypedef
? CvContourScannerの定義はヘッダファイルにない
? cvStartFindContours(img,storage)は閾値処理済み画像と、
  輪郭オブジェクトの確保につかうメモリストレージを引数にとり
  CvContourScanner を生成
? cvFindNextContourは、輪郭を一つ取得
? cvEndFindContoursはCvContourScanner を破棄し、
  全部の輪郭データを取得 メンバ変数をたどって別の輪郭の取得も
可能
? cvClearMemStorage(storage)で輪郭データの解放+メモリストレー
  ジにメモリを返還
? cvFindNextContour,cvEndFindContourの戻り値は
  オブジェクトの先頭のメモリ構造を同じにすることで行う疑似継承
  における 疑似基底クラス

                わんくま同盟 東京勉強会 #69
Wrap8 輪郭抽出関数のラップ
public ref class CvContourScanner
{
  public:
    static const int DEFAULT_HEADER_SIZE = sizeof( ::CvContour);

   CvContourScanner(IplImage^ image,CvMemStorage^ storage,
              int header_size, int mode, int method,CvPoint^ offset)
   {
     ptr_ =::cvStartFindContours(image->ptr_,storage->ptr_,
                             header_size,mode,method,*offset->ptr_);
   }

   static CvContourScanner^ cvStartFindContours(
            IplImage^ image,CvMemStorage^ storage, int header_size,
                    int mode, int method,CvPoint^ offset)
   {
       return = gcnew CvContourScanner(image,storage,header_size,
                                   mode,method,offset);
   }
                         わんくま同盟 東京勉強会 #69
Wrap8 輪郭抽出関数のラップ
CvContour^ cvFindNextContour()
{
  ::CvContour* contour= reinterpret_cast< ::CvContour*>
                          ( ::cvFindNextContour(this->ptr_) );
  if(contour != nullptr)
  {
       return gcnew CvContour(contour);
  }
  else
  {
    return nullptr;
  }
}

static CvContour^ cvFindNextContour(CvContourScanner^ scanner)
{
   return scanner->cvFindNextContour();
}

                     わんくま同盟 東京勉強会 #69
Wrap8 輪郭抽出関数のラップ
CvContour^ cvEndFindContours()
{
  pin_ptr< ::_CvContourScanner* > pp = &(this->ptr_);
  ::CvContour* ptr = reinterpret_cast< ::CvContour*>
                                      (::cvEndFindContours(pp));
  pp = nullptr; this->ptr_ = nullptr;
  CvContour^ contour = gcnew CvContour();
  contour->ptr_ = ptr;
  return contour;
}

static CvContour^ cvEndFindContours(CvContourScanner^ scanner)
{
  return scanner->cvEndFindContours();
}




                     わんくま同盟 東京勉強会 #69
Wrap8 輪郭抽出関数のラップ
~CvContourScanner()
{
    this->!CvContourScanner();
}
  !CvContourScanner()
  {
    if(!noalloc_)
    {
      if(this->ptr_ != nullptr)
      {
        pin_ptr< ::_CvContourScanner* > pp = &(this->ptr_);
        ::CvContour* contour = reinterpret_cast< ::CvContour*>
                                      ( ::cvEndFindContours(pp) );
        ::cvClearMemStorage(contour->storage);
        this->ptr_ = nullptr;
      }
    }
}

                      わんくま同盟 東京勉強会 #69
Wrap8 輪郭抽出関数のラップ(C++/CLI)
    private:
       bool noalloc_;

    internal:
    _CvContourScanner* ptr_;
}

struct _CvContourScanner{};




                           わんくま同盟 東京勉強会 #69
Wrap8 輪郭抽出関数のラップ(C++/CLI)
public ref class CvContour
{
  public:
      CvContour(){ noalloc_ = false;   this->ptr_ = nullptr;   }

      ~CvContour() {this->!CvContour();}
      !CvContour()
      {
        if(!noalloc_) { ::cvClearMemStorage(ptr_->storage);    }
      }
  private:
      bool noalloc_;
  internal:
      CvContour( ::CvContour* ptr)
      {noalloc_ = true; this->ptr_ = ptr; }
      ::CvContour* ptr_;
};


                        わんくま同盟 東京勉強会 #69
輪郭抽出関数のラップ

? CvContourScannerがヘッダファイルに定義がないので、
  自分で空の構造体を作成する。
  (ポインタのサイズが分かれば正常に動作するはず)
? CvContourScannerオブジェクトはcvStartFindContours()で作成し、
   cvEndFindContours()で破棄する
   cvEnd~を呼び忘れても良いように、データが破棄されていなけれ
ば、
  ファイナライザで呼び出す。
? 輪郭データの破壊はcvEndFindContours()で返されるオブジェクト
   (全輪郭の代表に)に対して::cvClearMemStorage()を呼び出すこと
   で行う。(ファイナライザで呼び出す。)
? cvFindNextContourの戻り値の輪郭データは開放してはいけないので
    cvFindNext~では非破壊コンストラクタ、
  cvEndFind~では通常のコンストラクタで輪郭オブジェクトを
  作成する(cvContour)
                  わんくま同盟 東京勉強会 #69
もう一回実行してみる




  わんくま同盟 東京勉強会 #69
輪郭?矩形 描画関連 (C++/CLI)
public ref class IplImage
{
   public:
   // ~~略~~
     static void cvDrawContours(IplImage^ img, CvContour^ contour,
                      CvScalar^ external_color,CvScalar^ hole_color,
         int max_level, int thickness ,int line_type, CvPoint^ offset)
     {
       ::cvDrawContours(img->ptr_,reinterpret_cast<CvSeq*>
         (contour->ptr_), *external_color->ptr_, *hole_color->ptr_,
                   max_level,thickness,line_type, *offset->ptr_);
     }
     static void cvRectangleR(IplImage^ img, CvRect^ r,
            CvScalar^ color,int thickness, int line_type, int shift)
     {
        ::cvRectangleR(img->ptr_,*r->ptr_,*color->ptr_,
                                        thickness,line_type,shift);
     }
};
                         わんくま同盟 東京勉強会 #69
続?実行コード C#
class Program
{
  static void Main(string[] args)
  {
     // ~~略~~
     CvMemStorage storage = new CvMemStorage(0);
     CvContourScanner scanner = new CvContourScanner
          (img2,storage,CvContourScanner.DEFAULT_HEADER_SIZE,
                                       1,2,new CvPoint(0,0));

   List<CvRect> list = new List<CvRect>();
   CvContour scanningContour = null;




                     わんくま同盟 東京勉強会 #69
続?実行コード C#
do
{
     scanningContour = scanner.cvFindNextContour();
     if (scanningContour!= null)
     {
        list.Add(scanningContour.rect);
     }
}
while (scanningContour != null);

CvContour endContour = scanner.cvEndFindContours();
IplImage.cvDrawContours(img2,endContour,new CvScalar(64,64,64,64),
       new CvScalar(255,255,255,255), 1,2,8, new CvPoint(0, 0));

GUI.cvShowImage( "window" , img2);
GUI.cvWaitKey(0);




                        わんくま同盟 東京勉強会 #69
続?実行コード C#
      foreach(CvRect r in list)
      {
        IplImage.cvRectangleR(img2, r,
                      new CvScalar(128, 128,128,128), 2, 8, 0);
      }

      endContour.Dispose();
      storage.Dispose();

      GUI.cvShowImage( "window" , img2);
      GUI.cvWaitKey(0);

      img2.Dispose();
      GUI.cvDestroyWindow( "window" );
  }
};


                        わんくま同盟 東京勉強会 #69
わんくま同盟 東京勉強会 #69
わんくま同盟 東京勉強会 #69
わんくま同盟 東京勉強会 #69
わんくま同盟 東京勉強会 #69
わんくま同盟 東京勉強会 #69
まとめ



わんくま同盟 東京勉強会 #69
まとめ

? ネイティブオブジェクトはポインタで管理し
  コンストラクタでnew,ファイナライザでdeleteす
  る
? ポインタ等の露出する部分はinternalにして
  外部から見えないようにする。
? メンバ変数はプロパティとして公開
? ダブルポインタはpin_ptrでアドレスを固定
? char*?System.String等はMarshalクラスで変換



            わんくま同盟 東京勉強会 #69
まとめ
? 複合型メンバ変数は、ポインタを受け取るコン
  ストラクタを使い、マネージド型(ラッパークラ
  ス)のプロパティとして公開する。
  解放は親が解放される事で行われるので、
  ファイナライザで開放しないようにする。
? マネージドオブジェクトが消滅するとき
  ラップしたネイティブオブジェクトも
  解放(delete)してよいのか注意し、
? よくない場合は、
  コンストラクタでフラグを立てるなどの方法で、
  ファイナライザでの解放を防ぐ

        わんくま同盟 東京勉強会 #69
ご清聴ありがとうございました




    わんくま同盟 東京勉強会 #69
Ad

Recommended

颁++颁尝滨で、ネイティブ颁の保守开発に.狈贰罢を使って楽をしよう
颁++颁尝滨で、ネイティブ颁の保守开発に.狈贰罢を使って楽をしよう
Study Group by SciencePark Corp.
?
(文献紹介)Deep Unrolling: Learned ISTA (LISTA)
(文献紹介)Deep Unrolling: Learned ISTA (LISTA)
Morpho, Inc.
?
[DL輪読会]Wasserstein GAN/Towards Principled Methods for Training Generative Adv...
[DL輪読会]Wasserstein GAN/Towards Principled Methods for Training Generative Adv...
Deep Learning JP
?
竞技フ?ロク?ラミンク?におけるコート?の书き方とその利便性
竞技フ?ロク?ラミンク?におけるコート?の书き方とその利便性
Hibiki Yamashiro
?
【DL輪読会】Perceiver io a general architecture for structured inputs &amp; outputs
【DL輪読会】Perceiver io a general architecture for structured inputs &amp; outputs
Deep Learning JP
?
摆顿尝轮読会闭画像を使った厂颈尘2搁别补濒の现况
摆顿尝轮読会闭画像を使った厂颈尘2搁别补濒の现况
Deep Learning JP
?
最近のDeep Learning (NLP) 界隈におけるAttention事情
最近のDeep Learning (NLP) 界隈におけるAttention事情
Yuta Kikuchi
?
5分でわかるかもしれない驳濒尘苍别迟
5分でわかるかもしれない驳濒尘苍别迟
Nagi Teramo
?
机械学习モデルの列挙
机械学习モデルの列挙
Satoshi Hara
?
[DL輪読会]Learning convolutional neural networks for graphs
[DL輪読会]Learning convolutional neural networks for graphs
Deep Learning JP
?
Fisher Vectorによる画像認識
Fisher Vectorによる画像認識
Takao Yamanaka
?
[DL輪読会]Deep Learning 第18章 分配関数との対峙
[DL輪読会]Deep Learning 第18章 分配関数との対峙
Deep Learning JP
?
惭补迟濒补苍迟颈蝉?のニューラルネットワークポテンシャル笔贵笔の适用范囲拡张
惭补迟濒补苍迟颈蝉?のニューラルネットワークポテンシャル笔贵笔の适用范囲拡张
Preferred Networks
?
「世界モデル」と関连研究について
「世界モデル」と関连研究について
Masahiro Suzuki
?
数学で解き明かす深层学习の原理
数学で解き明かす深层学习の原理
Taiji Suzuki
?
叠辞辞蝉迟のあるプログラミング生活
叠辞辞蝉迟のあるプログラミング生活
Akira Takahashi
?
セミハ?ラメトリック推论の基础
セミハ?ラメトリック推论の基础
Daisuke Yoneoka
?
直交领域探索
直交领域探索
okuraofvegetable
?
Active Learning と Bayesian Neural Network
Active Learning と Bayesian Neural Network
Naoki Matsunaga
?
DNNコンパイラの歩みと最近の動向 ?TVMを中心に?
DNNコンパイラの歩みと最近の動向 ?TVMを中心に?
Takeo Imai
?
质的変数の相関?因子分析
质的変数の相関?因子分析
Mitsuo Shimohata
?
PFP:材料探索のための汎用Neural Network Potential_中郷_20220422POLセミナー
PFP:材料探索のための汎用Neural Network Potential_中郷_20220422POLセミナー
Matlantis
?
グラフニューラルネットワークとグラフ组合せ问题
グラフニューラルネットワークとグラフ组合せ问题
joisino
?
Dependent Types and Dynamics of Natural Language
Dependent Types and Dynamics of Natural Language
Daisuke BEKKI
?
Deep Learningのための専用プロセッサ「MN-Core」の開発と活用(2022/10/19東大大学院「 融合情報学特別講義Ⅲ」)
Deep Learningのための専用プロセッサ「MN-Core」の開発と活用(2022/10/19東大大学院「 融合情報学特別講義Ⅲ」)
Preferred Networks
?
【DL輪読会】Llama 2: Open Foundation and Fine-Tuned Chat Models
【DL輪読会】Llama 2: Open Foundation and Fine-Tuned Chat Models
Deep Learning JP
?
論文紹介 wav2vec: Unsupervised Pre-training for Speech Recognition
論文紹介 wav2vec: Unsupervised Pre-training for Speech Recognition
YosukeKashiwagi1
?
Introduction to C++ over CLI
Introduction to C++ over CLI
建興 王
?
碍颈苍别肠迟深度情报処理入门
碍颈苍别肠迟深度情报処理入门
伸男 伊藤
?

More Related Content

What's hot (20)

机械学习モデルの列挙
机械学习モデルの列挙
Satoshi Hara
?
[DL輪読会]Learning convolutional neural networks for graphs
[DL輪読会]Learning convolutional neural networks for graphs
Deep Learning JP
?
Fisher Vectorによる画像認識
Fisher Vectorによる画像認識
Takao Yamanaka
?
[DL輪読会]Deep Learning 第18章 分配関数との対峙
[DL輪読会]Deep Learning 第18章 分配関数との対峙
Deep Learning JP
?
惭补迟濒补苍迟颈蝉?のニューラルネットワークポテンシャル笔贵笔の适用范囲拡张
惭补迟濒补苍迟颈蝉?のニューラルネットワークポテンシャル笔贵笔の适用范囲拡张
Preferred Networks
?
「世界モデル」と関连研究について
「世界モデル」と関连研究について
Masahiro Suzuki
?
数学で解き明かす深层学习の原理
数学で解き明かす深层学习の原理
Taiji Suzuki
?
叠辞辞蝉迟のあるプログラミング生活
叠辞辞蝉迟のあるプログラミング生活
Akira Takahashi
?
セミハ?ラメトリック推论の基础
セミハ?ラメトリック推论の基础
Daisuke Yoneoka
?
直交领域探索
直交领域探索
okuraofvegetable
?
Active Learning と Bayesian Neural Network
Active Learning と Bayesian Neural Network
Naoki Matsunaga
?
DNNコンパイラの歩みと最近の動向 ?TVMを中心に?
DNNコンパイラの歩みと最近の動向 ?TVMを中心に?
Takeo Imai
?
质的変数の相関?因子分析
质的変数の相関?因子分析
Mitsuo Shimohata
?
PFP:材料探索のための汎用Neural Network Potential_中郷_20220422POLセミナー
PFP:材料探索のための汎用Neural Network Potential_中郷_20220422POLセミナー
Matlantis
?
グラフニューラルネットワークとグラフ组合せ问题
グラフニューラルネットワークとグラフ组合せ问题
joisino
?
Dependent Types and Dynamics of Natural Language
Dependent Types and Dynamics of Natural Language
Daisuke BEKKI
?
Deep Learningのための専用プロセッサ「MN-Core」の開発と活用(2022/10/19東大大学院「 融合情報学特別講義Ⅲ」)
Deep Learningのための専用プロセッサ「MN-Core」の開発と活用(2022/10/19東大大学院「 融合情報学特別講義Ⅲ」)
Preferred Networks
?
【DL輪読会】Llama 2: Open Foundation and Fine-Tuned Chat Models
【DL輪読会】Llama 2: Open Foundation and Fine-Tuned Chat Models
Deep Learning JP
?
論文紹介 wav2vec: Unsupervised Pre-training for Speech Recognition
論文紹介 wav2vec: Unsupervised Pre-training for Speech Recognition
YosukeKashiwagi1
?
机械学习モデルの列挙
机械学习モデルの列挙
Satoshi Hara
?
[DL輪読会]Learning convolutional neural networks for graphs
[DL輪読会]Learning convolutional neural networks for graphs
Deep Learning JP
?
Fisher Vectorによる画像認識
Fisher Vectorによる画像認識
Takao Yamanaka
?
[DL輪読会]Deep Learning 第18章 分配関数との対峙
[DL輪読会]Deep Learning 第18章 分配関数との対峙
Deep Learning JP
?
惭补迟濒补苍迟颈蝉?のニューラルネットワークポテンシャル笔贵笔の适用范囲拡张
惭补迟濒补苍迟颈蝉?のニューラルネットワークポテンシャル笔贵笔の适用范囲拡张
Preferred Networks
?
「世界モデル」と関连研究について
「世界モデル」と関连研究について
Masahiro Suzuki
?
数学で解き明かす深层学习の原理
数学で解き明かす深层学习の原理
Taiji Suzuki
?
叠辞辞蝉迟のあるプログラミング生活
叠辞辞蝉迟のあるプログラミング生活
Akira Takahashi
?
セミハ?ラメトリック推论の基础
セミハ?ラメトリック推论の基础
Daisuke Yoneoka
?
Active Learning と Bayesian Neural Network
Active Learning と Bayesian Neural Network
Naoki Matsunaga
?
DNNコンパイラの歩みと最近の動向 ?TVMを中心に?
DNNコンパイラの歩みと最近の動向 ?TVMを中心に?
Takeo Imai
?
质的変数の相関?因子分析
质的変数の相関?因子分析
Mitsuo Shimohata
?
PFP:材料探索のための汎用Neural Network Potential_中郷_20220422POLセミナー
PFP:材料探索のための汎用Neural Network Potential_中郷_20220422POLセミナー
Matlantis
?
グラフニューラルネットワークとグラフ组合せ问题
グラフニューラルネットワークとグラフ组合せ问题
joisino
?
Dependent Types and Dynamics of Natural Language
Dependent Types and Dynamics of Natural Language
Daisuke BEKKI
?
Deep Learningのための専用プロセッサ「MN-Core」の開発と活用(2022/10/19東大大学院「 融合情報学特別講義Ⅲ」)
Deep Learningのための専用プロセッサ「MN-Core」の開発と活用(2022/10/19東大大学院「 融合情報学特別講義Ⅲ」)
Preferred Networks
?
【DL輪読会】Llama 2: Open Foundation and Fine-Tuned Chat Models
【DL輪読会】Llama 2: Open Foundation and Fine-Tuned Chat Models
Deep Learning JP
?
論文紹介 wav2vec: Unsupervised Pre-training for Speech Recognition
論文紹介 wav2vec: Unsupervised Pre-training for Speech Recognition
YosukeKashiwagi1
?

Viewers also liked (8)

Introduction to C++ over CLI
Introduction to C++ over CLI
建興 王
?
碍颈苍别肠迟深度情报処理入门
碍颈苍别肠迟深度情报処理入门
伸男 伊藤
?
窜别谤辞贵辞谤尘补迟迟别谤に见る颁#で最速のシリアライザを作成する100亿の方法
窜别谤辞贵辞谤尘补迟迟别谤に见る颁#で最速のシリアライザを作成する100亿の方法
Yoshifumi Kawai
?
Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用
Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用
Yoshifumi Kawai
?
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
Yoshifumi Kawai
?
RuntimeUnitTestToolkit for Unity
RuntimeUnitTestToolkit for Unity
Yoshifumi Kawai
?
NextGen Server/Client Architecture - gRPC + Unity + C#
NextGen Server/Client Architecture - gRPC + Unity + C#
Yoshifumi Kawai
?
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
Yoshifumi Kawai
?
Introduction to C++ over CLI
Introduction to C++ over CLI
建興 王
?
碍颈苍别肠迟深度情报処理入门
碍颈苍别肠迟深度情报処理入门
伸男 伊藤
?
窜别谤辞贵辞谤尘补迟迟别谤に见る颁#で最速のシリアライザを作成する100亿の方法
窜别谤辞贵辞谤尘补迟迟别谤に见る颁#で最速のシリアライザを作成する100亿の方法
Yoshifumi Kawai
?
Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用
Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用
Yoshifumi Kawai
?
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
Yoshifumi Kawai
?
RuntimeUnitTestToolkit for Unity
RuntimeUnitTestToolkit for Unity
Yoshifumi Kawai
?
NextGen Server/Client Architecture - gRPC + Unity + C#
NextGen Server/Client Architecture - gRPC + Unity + C#
Yoshifumi Kawai
?
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
Yoshifumi Kawai
?
Ad

Similar to T69 c++cli ネイティブライブラリラッピング入門 (20)

C++0x 言語の未来を語る
C++0x 言語の未来を語る
Akira Takahashi
?
Python physicalcomputing
Python physicalcomputing
Noboru Irieda
?
中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr
Genya Murakami
?
Introduction of Python
Introduction of Python
Tomoya Nakayama
?
わんくま同盟大阪勉强会#61
わんくま同盟大阪勉强会#61
TATSUYA HAYAMIZU
?
颁#勉强会
颁#勉强会
hakugakucafe
?
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
fuzzysphere
?
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#
信之 岩永
?
emc++ chapter32
emc++ chapter32
Tatsuki SHIMIZU
?
颁++0虫総復习
颁++0虫総復习
道化師 堂華
?
20130329 rtm4
20130329 rtm4
openrtm
?
第2回勉强会スライド
第2回勉强会スライド
koturn 0;
?
Python で munin plugin を書いてみる
Python で munin plugin を書いてみる
ftnk
?
Php in ruby
Php in ruby
do_aki
?
Boost tour 1_40_0
Boost tour 1_40_0
Akira Takahashi
?
C++0x 言語の未来を語る
C++0x 言語の未来を語る
Akira Takahashi
?
Python physicalcomputing
Python physicalcomputing
Noboru Irieda
?
中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr
Genya Murakami
?
わんくま同盟大阪勉强会#61
わんくま同盟大阪勉强会#61
TATSUYA HAYAMIZU
?
Wrapping a C++ library with Cython
Wrapping a C++ library with Cython
fuzzysphere
?
20130329 rtm4
20130329 rtm4
openrtm
?
第2回勉强会スライド
第2回勉强会スライド
koturn 0;
?
Python で munin plugin を書いてみる
Python で munin plugin を書いてみる
ftnk
?
Php in ruby
Php in ruby
do_aki
?
Ad

More from 伸男 伊藤 (6)

罢119冲5年间の试行错误で进化した惭痴笔痴惭パターン
罢119冲5年间の试行错误で进化した惭痴笔痴惭パターン
伸男 伊藤
?
T90 きっと怖くないmvvm & mvpvm
T90 きっと怖くないmvvm & mvpvm
伸男 伊藤
?
没セッション 知識ゼロから学んだソフトウェアテスト
没セッション 知識ゼロから学んだソフトウェアテスト
伸男 伊藤
?
わんくまT84 kinect深度情報処理入門
わんくまT84 kinect深度情報処理入門
伸男 伊藤
?
わんくまT78 mfcを始めようとしてみた
わんくまT78 mfcを始めようとしてみた
伸男 伊藤
?
罢119冲5年间の试行错误で进化した惭痴笔痴惭パターン
罢119冲5年间の试行错误で进化した惭痴笔痴惭パターン
伸男 伊藤
?
T90 きっと怖くないmvvm & mvpvm
T90 きっと怖くないmvvm & mvpvm
伸男 伊藤
?
没セッション 知識ゼロから学んだソフトウェアテスト
没セッション 知識ゼロから学んだソフトウェアテスト
伸男 伊藤
?
わんくまT84 kinect深度情報処理入門
わんくまT84 kinect深度情報処理入門
伸男 伊藤
?
わんくまT78 mfcを始めようとしてみた
わんくまT78 mfcを始めようとしてみた
伸男 伊藤
?

T69 c++cli ネイティブライブラリラッピング入門

  • 1. C++/CLI ネイティブライブラリラッピン グ入門 暁 紫電 わんくま同盟 東京勉強会 #69
  • 2. 自己紹介 ? HN 暁 紫電 ? Twitter @akatukisiden ? 年齢 25歳 ? フリープログラマー ? 使用言語 C++、C++/CLI、C# ? 現在のお仕事 Kinect(OpenNI)、OpenCV、MIDI わんくま同盟 東京勉強会 #69
  • 3. マネージ コードとネイティブ コード 相互運用テクノロジ ? P/Invoke ? COM ? C++/CLI わんくま同盟 東京勉強会 #69
  • 4. Platform Invoke (P/Invoke) ? DLLからC スタイルのネイティブ関数を呼び出す。 ? ヘッダファイルの情報を .NET側に用意する必要がある。 ? .NET Frameworkの内部でよく使用されている ? 引数のマネージ←→ネイティブ変換コストに加 え 一回の呼び出しでx86命令10~30個分の オーバーヘッドが係る ? どんな関数でも正常に呼び出せるわけではない わんくま同盟 東京勉強会 #69
  • 5. COM相互運用 ? I Unknown ? マネージ コードからCOMインターフェイスを使 用、 またはマネージAPIを COMインターフェイス として 公開する機能 ? Office関連や、WinRTなどで使われている ? 時間コストはC++/CLIと同程度 わんくま同盟 東京勉強会 #69
  • 6. C++/CLI ? Cヰ ? マネージ コードおよびネイティブ コード が混在するアセンブリを作成する ? P/Invokeとは違い、見た目は普通の マネージオブジェクトにすることが可能 ? おそらく、どんなクラス?関数でもラップ 可能 わんくま同盟 東京勉強会 #69
  • 7. 今回は 画像処理ライブラリOpenCVのラップを通し て C++/CLIを用いた .NETでのネイティブコードの利用について 紹介します。 ※ ヘッダファイルに宣言と定義、両方まとめて書いてい ますが、実際は分けて書いてください わんくま同盟 東京勉強会 #69
  • 8. マネージ型 値?参照\デフォ ルト Public private アクセス指定子 参照型 ref struct; ref class; 値型 value struct; value class; ? class structの使い方はC++相当 ? 値型?参照型はその前につけるvalue/refで決ま る。 ? 参照型のハンドルは型名の後ろに^をつけて表 す わんくま同盟 東京勉強会 #69
  • 10. Wrap1 最低限のラップ (CvSize) public ref class CvSize { public: CvSize(void) { ptr = new ::CvSize; } ~CvSize() { this -> !CvSize(); } !CvSize() { delete ptr; } internal: ::CvSize* ptr; }; わんくま同盟 東京勉強会 #69
  • 11. Wrap1 最低限のラップ (CvSize) ? ref class ? ネイティブオブジェクトのポインタを internalメンバとして持たせる。 ? コンストラクタでオブジェクトを生成 ? デストラクタ/ファイナライザで破棄 ? デストラクタ(~Class())はDispose(true)相当 ? ファイナライザ(!Class())はDispose(false) 相当 ? ファイナライザは通常の関数として呼び出し可 能 わんくま同盟 東京勉強会 #69
  • 12. Wrap2 基本型メンバ変数の公開 (CvSize) public ref class CvSize { // ~~略~~ public: property int width { int get(){ return ptr_->width;} void set( int value ){ ptr_->width = value; } } property int height { int get(){return ptr_->height;} void set(int value){ptr_->height = value; } } internal: ::CvSize* ptr_ }; わんくま同盟 東京勉強会 #69
  • 13. Wrap2 基本型メンバ変数の公開 (CvSize) ? メンバ変数はプロパティとして公開する ? Internalポインタを通してメンバ変数にアクセス ? 基本型はマネージ、ネイティブ間で互換性有り わんくま同盟 東京勉強会 #69
  • 14. OpenCV画像クラス IplImageをラップする わんくま同盟 東京勉強会 #69
  • 15. Wrap3 ポインタで管理するクラス (IplImage) public ref class IplImage { public: IplImage(CvSize^ size,int depth,int channels) { ptr = ::cvCreateImage(*size->ptr,depth,channels);} ~IplImage(){ this->!IplImage(); } !IplImage() { pin_ptr<::IplImage*> pin_Image = &ptr; ::cvReleaseImage(pin_Image); } internal: ::IplImage* ptr; }; わんくま同盟 東京勉強会 #69
  • 16. Wrap3 ポインタで管理するクラス (IplImage) ? 独自の生成関数、解放関数を持ち、 インスタンスはポインタで管理するクラス ? 生成?解放関数自体はコンストラクタ、 ファイナライザ内で呼び出す。 ? ダブルポインタを引数に取る関数(解放関数)は そのままではガベコレでアドレスが変わる 可能性があるというエラーが発生するので pin_ptr<T*>でアドレスを固定する わんくま同盟 東京勉強会 #69
  • 17. 画像ファイル読み込み関数 cvLoadImageを コンストラクタとしてラップ わんくま同盟 東京勉強会 #69
  • 18. Wrap4 文字列変換(cvLoadImage) public ref class IplImage { // ~~略~~ public: IplImage(System::String^ str, int iscolor) { const char* chars = (const char*) System::Runtime::InteropServices::Marshal ::StringToHGlobalAnsi(str).ToPo inter(); this->ptr = ::cvLoadImage(chars ,iscolor); System::Runtime::InteropServices::Marshal ::FreeHGlobal(System::IntPtr((vo id*)chars)); } // ~~略~~ }; わんくま同盟 東京勉強会 #69
  • 19. Wrap4 文字列変換(cvLoadImage) ? System.Stringからchar*に変換 ? マネージ?アンマネージの変換用の関数をまと めたMarshalクラスのメンバを使用 ? IntPtr Marshal::StringToHGlobalAnsi(string); String の内容をアンマネージ メモリにコピーし、 コピー時に ANSI 形式に変換します。 ? void Marshal::FreeHGlobal(IntPtr); アンマネージメモリから割り当てられたメモリを 解放します。 わんくま同盟 東京勉強会 #69
  • 20. しきい値処理関数 cvThresholdをラップする わんくま同盟 東京勉強会 #69
  • 21. Wrap5 関数のラップ(cvThreshold) public ref class IplImage { // ~~略~~ double cvThreshold( IplImage^ src, IplImage^ dst, double threshold, double max_value, int threshold_type ) { return ::cvThreshold(src->ptr, dst->ptr, threshold, max_value, threshold_type); } }; わんくま同盟 東京勉強会 #69
  • 22. Wrap5 関数のラップ(cvThreshold) ? オブジェクトを引数に取るものは 内部ポインタを(必要なら*をつけて)渡す。 ? 基本型引数はそのまま渡せる。 わんくま同盟 東京勉強会 #69
  • 24. 表示用関数郡 using namespace System::Runtime::InteropServices; public ref class GUI { public: static int cvNamedWindow( System::String^ str, int flags ) { const char* chars = (const char*) Marshal::StringToHGlobalAnsi(str).ToPointer(); int r = ::cvNamedWindow(chars,flags); Marshal::FreeHGlobal(System::IntPtr((void*)chars)); return r; } わんくま同盟 東京勉強会 #69
  • 25. 表示用関数 static void cvDestroyWindow( System::String^ str) { const char* chars = (const char*) Marshal::StringToHGlobalAnsi(str).ToPointer(); ::cvDestroyWindow( chars ); Marshal::FreeHGlobal( System::IntPtr((void*)chars)); } static void cvShowImage( System::String^ name,IplImage^ image) { const char* chars = (const char*) Marshal::StringToHGlobalAnsi(name).ToPointer(); ::cvShowImage( chars ,image->ptr); Marshal::FreeHGlobal( System::IntPtr((void*)chars)); } static int cvWaitKey(int delay) { return ::cvWaitKey(delay); } }; わんくま同盟 東京勉強会 #69
  • 26. 実行コード C# class Program { static void Main( string[] args) { GUI.cvNamedWindow( "window" , 1); IplImage loadedImage = new IplImage( "wankuma.png” , 0); GUI.cvShowImage( "window” , loadedImage); GUI.cvWaitKey(0); CvSize size = new CvSize(); size.width = loadedImage.width; size.height = loadedImage.height; IplImage img2 = new IplImage(size, loadedImage.depth, loadedImage.nChannels ); わんくま同盟 東京勉強会 #69
  • 27. 実行コード C# IplImage.cvThreshold(loadedImage, img2, 205, 255, 0); GUI.cvShowImage( "window" , img2); GUI.cvWaitKey(0); GUI.cvDestroyWindow( "window" ); } } わんくま同盟 東京勉強会 #69
  • 31. 二値画像から輪郭と その外接矩形を取得する わんくま同盟 東京勉強会 #69
  • 32. Wrap6 輪郭クラスはメモリストレージ CvMemStorage内に確保されるので まずはCvMemStorageをラップ わんくま同盟 東京勉強会 #69
  • 33. Wrap6 メモリストレージ CvMemStorage public ref class CvMemStorage { public: CvMemStorage( int block_size) { ptr_ = ::cvCreateMemStorage(block_size); } ~CvMemStorage() { this->!CvMemStorage();} !CvMemStorage() { pin_ptr< ::CvMemStorage* > p = &(this->ptr_ ); ::cvReleaseMemStorage( p ) ; } static void cvClearMemStorage(CvMemStorage^ storage) { ::cvClearMemStorage(storage->ptr_ ); } internal: ::CvMemStorage* ptr_; }; わんくま同盟 東京勉強会 #69
  • 34. Wrap6 メモリストレージ CvMemStorage ? コンストラクタでストレージ生成 ? ファイナライザで全解放 ? 割り当て済みストレージの解放関数 – void cvClearMemStorage(CvMemStorage^ storage); わんくま同盟 東京勉強会 #69
  • 35. wrap7 輪郭クラスCvContourは生成?破棄の方法が 特殊なので 先にそのメンバ変数rect(CvRect型)をラップ し プロパティとして公開する わんくま同盟 東京勉強会 #69
  • 36. Wrap7 複合型メンバ変数をプロパティとして公開 (CvContour::rect) Class AとそのメンバBをラップしたものが わんくま同盟 東京勉強会 #69
  • 37. Wrap7 複合型メンバ変数をプロパティとして公開 (CvContour::rect) ClassAのラッパーがBのラッパーをメンバに持つよ うに見えるようにする必要がある わんくま同盟 東京勉強会 #69
  • 38. Wrap7 複合型メンバ変数をプロパティとして公開 (CvContour::rect) public ref class CvContour { public: // ~~略~~ property CvRect^ rect { CvRect^ get() { return gcnew CvRect(&ptr_->rect); } void set(CvRect^ value) { *ptr_->rect = *(value->ptr_); } } internal: ::CvContour* ptr_; }; わんくま同盟 東京勉強会 #69
  • 39. Wrap7 複合型メンバ変数をプロパティとして公開 (CvContour::rect) public ref class CvRect ~CvRect() { { this->!CvRect();} public: // ~~略~~ !CvRect() CvRect() { { if(!noalloc_) noalloc_ = false; { this-> ptr_ = new ::CvRect; delete ptr_; } } this->ptr_ = nullptr; CvRect( ::CvRect* pRect) } { private: noalloc_ = true; bool noalloc_ ; this->ptr_ = pRect; } Internal: ::CvRect* ptr_; } わんくま同盟 東京勉強会 #69
  • 40. Wrap7 複合型メンバ変数をプロパティとして公開 (CvContour::rect) ? プロパティのgetterではポインタを受け取 るコンストラクタを用いて、 ラッパーオブジェクトを作成(gcnew)する。 ? ポインタを受け取るコンストラクタで初期 化した場合は非破壊フラグを立て、ファイ ナライザでdeleteしないようにする。 ? setterではvalue側の内部ポインタの指す値 をコピーする。 わんくま同盟 東京勉強会 #69
  • 42. Wrap8 輪郭スキャン関連 使い方が複雑なので まずC++側でどのように使うかを確認 わんくま同盟 東京勉強会 #69
  • 43. Wrap8 輪郭スキャン関連(C++) IplImage img_th = 閾値処理後の画像 CvContourScanner scanner = cvStartFindContours(img_th, storage); CvContour* contour; do { contour = reinterpret_cast< CvContour*> ( cvFindNextContour(scanner) ); if(contour != nullptr) { CvRect rect = contour->rect; } } while (contour != nullptr); contour = reinterpret_cast<CvContour*>(cvEndFindContours(&scanner)); cvClearMemStorage(contour->storage); わんくま同盟 東京勉強会 #69
  • 44. Wrap8 輪郭スキャン関連(C++) ? CvContourScanner は_CvContourScanner*のtypedef ? CvContourScannerの定義はヘッダファイルにない ? cvStartFindContours(img,storage)は閾値処理済み画像と、 輪郭オブジェクトの確保につかうメモリストレージを引数にとり CvContourScanner を生成 ? cvFindNextContourは、輪郭を一つ取得 ? cvEndFindContoursはCvContourScanner を破棄し、 全部の輪郭データを取得 メンバ変数をたどって別の輪郭の取得も 可能 ? cvClearMemStorage(storage)で輪郭データの解放+メモリストレー ジにメモリを返還 ? cvFindNextContour,cvEndFindContourの戻り値は オブジェクトの先頭のメモリ構造を同じにすることで行う疑似継承 における 疑似基底クラス わんくま同盟 東京勉強会 #69
  • 45. Wrap8 輪郭抽出関数のラップ public ref class CvContourScanner { public: static const int DEFAULT_HEADER_SIZE = sizeof( ::CvContour); CvContourScanner(IplImage^ image,CvMemStorage^ storage, int header_size, int mode, int method,CvPoint^ offset) { ptr_ =::cvStartFindContours(image->ptr_,storage->ptr_, header_size,mode,method,*offset->ptr_); } static CvContourScanner^ cvStartFindContours( IplImage^ image,CvMemStorage^ storage, int header_size, int mode, int method,CvPoint^ offset) { return = gcnew CvContourScanner(image,storage,header_size, mode,method,offset); } わんくま同盟 東京勉強会 #69
  • 46. Wrap8 輪郭抽出関数のラップ CvContour^ cvFindNextContour() { ::CvContour* contour= reinterpret_cast< ::CvContour*> ( ::cvFindNextContour(this->ptr_) ); if(contour != nullptr) { return gcnew CvContour(contour); } else { return nullptr; } } static CvContour^ cvFindNextContour(CvContourScanner^ scanner) { return scanner->cvFindNextContour(); } わんくま同盟 東京勉強会 #69
  • 47. Wrap8 輪郭抽出関数のラップ CvContour^ cvEndFindContours() { pin_ptr< ::_CvContourScanner* > pp = &(this->ptr_); ::CvContour* ptr = reinterpret_cast< ::CvContour*> (::cvEndFindContours(pp)); pp = nullptr; this->ptr_ = nullptr; CvContour^ contour = gcnew CvContour(); contour->ptr_ = ptr; return contour; } static CvContour^ cvEndFindContours(CvContourScanner^ scanner) { return scanner->cvEndFindContours(); } わんくま同盟 東京勉強会 #69
  • 48. Wrap8 輪郭抽出関数のラップ ~CvContourScanner() { this->!CvContourScanner(); } !CvContourScanner() { if(!noalloc_) { if(this->ptr_ != nullptr) { pin_ptr< ::_CvContourScanner* > pp = &(this->ptr_); ::CvContour* contour = reinterpret_cast< ::CvContour*> ( ::cvEndFindContours(pp) ); ::cvClearMemStorage(contour->storage); this->ptr_ = nullptr; } } } わんくま同盟 東京勉強会 #69
  • 49. Wrap8 輪郭抽出関数のラップ(C++/CLI) private: bool noalloc_; internal: _CvContourScanner* ptr_; } struct _CvContourScanner{}; わんくま同盟 東京勉強会 #69
  • 50. Wrap8 輪郭抽出関数のラップ(C++/CLI) public ref class CvContour { public: CvContour(){ noalloc_ = false; this->ptr_ = nullptr; } ~CvContour() {this->!CvContour();} !CvContour() { if(!noalloc_) { ::cvClearMemStorage(ptr_->storage); } } private: bool noalloc_; internal: CvContour( ::CvContour* ptr) {noalloc_ = true; this->ptr_ = ptr; } ::CvContour* ptr_; }; わんくま同盟 東京勉強会 #69
  • 51. 輪郭抽出関数のラップ ? CvContourScannerがヘッダファイルに定義がないので、 自分で空の構造体を作成する。 (ポインタのサイズが分かれば正常に動作するはず) ? CvContourScannerオブジェクトはcvStartFindContours()で作成し、 cvEndFindContours()で破棄する cvEnd~を呼び忘れても良いように、データが破棄されていなけれ ば、 ファイナライザで呼び出す。 ? 輪郭データの破壊はcvEndFindContours()で返されるオブジェクト (全輪郭の代表に)に対して::cvClearMemStorage()を呼び出すこと で行う。(ファイナライザで呼び出す。) ? cvFindNextContourの戻り値の輪郭データは開放してはいけないので cvFindNext~では非破壊コンストラクタ、 cvEndFind~では通常のコンストラクタで輪郭オブジェクトを 作成する(cvContour) わんくま同盟 東京勉強会 #69
  • 53. 輪郭?矩形 描画関連 (C++/CLI) public ref class IplImage { public: // ~~略~~ static void cvDrawContours(IplImage^ img, CvContour^ contour, CvScalar^ external_color,CvScalar^ hole_color, int max_level, int thickness ,int line_type, CvPoint^ offset) { ::cvDrawContours(img->ptr_,reinterpret_cast<CvSeq*> (contour->ptr_), *external_color->ptr_, *hole_color->ptr_, max_level,thickness,line_type, *offset->ptr_); } static void cvRectangleR(IplImage^ img, CvRect^ r, CvScalar^ color,int thickness, int line_type, int shift) { ::cvRectangleR(img->ptr_,*r->ptr_,*color->ptr_, thickness,line_type,shift); } }; わんくま同盟 東京勉強会 #69
  • 54. 続?実行コード C# class Program { static void Main(string[] args) { // ~~略~~ CvMemStorage storage = new CvMemStorage(0); CvContourScanner scanner = new CvContourScanner (img2,storage,CvContourScanner.DEFAULT_HEADER_SIZE, 1,2,new CvPoint(0,0)); List<CvRect> list = new List<CvRect>(); CvContour scanningContour = null; わんくま同盟 東京勉強会 #69
  • 55. 続?実行コード C# do { scanningContour = scanner.cvFindNextContour(); if (scanningContour!= null) { list.Add(scanningContour.rect); } } while (scanningContour != null); CvContour endContour = scanner.cvEndFindContours(); IplImage.cvDrawContours(img2,endContour,new CvScalar(64,64,64,64), new CvScalar(255,255,255,255), 1,2,8, new CvPoint(0, 0)); GUI.cvShowImage( "window" , img2); GUI.cvWaitKey(0); わんくま同盟 東京勉強会 #69
  • 56. 続?実行コード C# foreach(CvRect r in list) { IplImage.cvRectangleR(img2, r, new CvScalar(128, 128,128,128), 2, 8, 0); } endContour.Dispose(); storage.Dispose(); GUI.cvShowImage( "window" , img2); GUI.cvWaitKey(0); img2.Dispose(); GUI.cvDestroyWindow( "window" ); } }; わんくま同盟 東京勉強会 #69
  • 63. まとめ ? ネイティブオブジェクトはポインタで管理し コンストラクタでnew,ファイナライザでdeleteす る ? ポインタ等の露出する部分はinternalにして 外部から見えないようにする。 ? メンバ変数はプロパティとして公開 ? ダブルポインタはpin_ptrでアドレスを固定 ? char*?System.String等はMarshalクラスで変換 わんくま同盟 東京勉強会 #69
  • 64. まとめ ? 複合型メンバ変数は、ポインタを受け取るコン ストラクタを使い、マネージド型(ラッパークラ ス)のプロパティとして公開する。 解放は親が解放される事で行われるので、 ファイナライザで開放しないようにする。 ? マネージドオブジェクトが消滅するとき ラップしたネイティブオブジェクトも 解放(delete)してよいのか注意し、 ? よくない場合は、 コンストラクタでフラグを立てるなどの方法で、 ファイナライザでの解放を防ぐ わんくま同盟 東京勉強会 #69
  • 65. ご清聴ありがとうございました わんくま同盟 東京勉強会 #69