2011-12-19 9 views
1

私はC++/CLIを使用してC++ライブラリ(ソースにアクセスできない)の周りに.NETラッパーを作成しています。 C++ライブラリは、C++/CLIで記述された.NETデリゲートをコールバックする必要があります。 Marshal :: GetFunctionPointerForDelegateを使用してC++ライブラリクラスにコールバック関数を割り当てます。ただし、この関数をアンマネージド側からコールバックすると、.NETデリゲート関数が同じメモリ位置にあることを確認する必要があります。自己メモリ固定型C++/CLIクラスの作成方法は?

最も簡単な方法は、.NETライブラリのユーザーに.NETオブジェクトを固定することですが、それは実際にはクリーンなデザインではなく、ユーザーが足で自分自身を撮影できるようにすることです。より良い方法は、作成時または関数/イベントによってトリガされるように.NETクラスを設計することです。

どうすればこのように設計できますか?このリンクによれば、http://msdn.microsoft.com/en-us/library/18xa23yk%28v=VS.100%29.aspxには、オブジェクトメンバーとして内部〜ピン付きポインタを持つことはできません。これは、固定されたポインタ参照を静的またはグローバル変数として作成できることを意味します。

私はこれらの2つのいずれかのようなことをしたいが、それをコンパイル/作業することはできない。

public ref class UserClass{ 
void createDotNetCPPWrapperClass() 
{ 
    m_class = gcnew DotNetCPPWrapperClass; 
} 

DotNetCPPWrapperClass^ m_class 

}; 


public ref class DotNetCPPWrapperClass{ 

static pin_ptr<DotNetCPPWrapperClass^> pinnedSelf; 

DotNetCPPWrapperClass() 
{ 
    pinnedSelf = this; 
} 
}; 

OR

public ref class UserClass{ 

void createDotNetCPPWrapperClass() 
{ 
    m_class = gcnew DotNetCPPWrapperClass; 
    m_class->setupImportantStuff(); 
} 

DotNetCPPWrapperClass^ m_class 

}; 


public ref class DotNetCPPWrapperClass{ 

static pin_ptr<DotNetCPPWrapperClass^> pinnedSelf; 

DotNetCPPWrapperClass(){} 

void setupImportantStuff() 
{ 
    pinnedSelf = this; 
} 

}; 
+0

フレームワークによって提供される 'GCHandle'または' HandleRef'構造を使って調査しましたか? –

+0

いいえ、しかし、現在グーグルではあります。どうも。 –

+0

Marshal :: GetFunctionPointerForDelegate()を使用する点は、これを行う必要がないことです。助けてください。 –

答えて

0

GCHandleあなたの問題を解決します。

public ref class Wrapper 
{ 

GChandle thisHandle; 
public: 
    Wrapper() 
    { 
    thisHandle = GCHandle.Alloc(this, GCHandleType::Normal); 
    } 

    ~Wrapper() // Dispose 
    { 
    if(thisHandle.IsAllocated) 
     thisHandle.Free; 
    } 

    !Wrapper() // Finalize 
    { 
    //Native resource releasing 
    } 
} 

ここで注意が必要な点がいくつかあります。

  1. あなたはに長時間ピン留めしたくない場合があります。一旦オブジェクトを固定すると、固定されたオブジェクトのアドレスを変更することができないため、固定されたオブジェクトの前に位置合わせされたオブジェクトをメモリに収集することはできません。だからガーベスのコレクションは無意味になります。私はGCHandleType::Normalとハンドルを割り当てて、それを回収不能にするだけでなく移動可能にすることに注意してください。
  2. GCが割り付けハンドルを持つオブジェクトを収集しようとしているかどうかわかりません。そのオブジェクトのファイナライザを呼び出します。 IMOこれは意味がありません。なぜならハンドルはGCコレクションからオブジェクトを保護するからです。したがって、C++/Cliのdeleteオペレータに電話し、C#のDispose()を呼び出してハンドルを解放することは非常に重要です。それらを呼び出すことを忘れると、オブジェクト全体がメモリリークになります。
0
public class MyClass { 

    private GCHandle gch; 

    public MyClass() { 
    gch=GCHandle.Alloc(this, GCHandleType.Pinned); 
    } 
} 
関連する問題