ハンス・パッサンが 望むようにこれが私のシナリオです。私は、パフォーマンスを尊重しながらネイティブ コードがすべてのハードワークを実行し、マネージ コードが GUI のみを担当する混合モード アプリケーションを使用しています。また、ユーザーは独自の C# コードを作成して参加します。ネイティブ クラスには C++、GUI とユーザー コードには C#、その間にラッパー クラスには C++/Cli があります。私のすべての C++ クラスの中には、計算の %90 を実行し、毎回異なるパラメーターが作成されるクラスがあります。それを NativeClass と呼びましょう。約あります。この NativeClass のインスタンスは 2000 個あり、計算を行う前に、いくつかのパラメーターに関連する適切なインスタンスを見つける必要があります。そこで、この目的のために、パラメーターがハッシュ コードである hash_map を考案しました。パラメータを取得したら、hash_map で適切なインスタンスを探し、それを見つけて、そのメソッドのいくつかを呼び出します。
ユーザーが C# コードを記述して計算に貢献すると、このクラスはコールバックによってこれらのコードを実行します。これは些細なことですが、ユーザーが作成した .Net クラスに関する情報が必要になることがあります。したがって、その特定の ManagedClass を NativeClass に何らかの方法でアタッチする必要があります。私の最初の解決策は、GChandle.Alloc() を使用してハンドル アドレスを転送することです。しかし、GC が適切に機能しないという懸念もあります。Hans は、Marshal.AllocCoTaskMem() と Marshal.StructureToPtr() を使用してアンマネージド メモリにマネージド オブジェクトを割り当てることを推奨しましたが、これは値型のクラスまたは構造体に有効であると私は信じています。refクラスはどうですか?GC が収集されるのを防ぎながら、NativeClass への参照を渡し、同時に GC を適切に機能させるにはどうすればよいですか?
サンプルコードは次のとおりです。
class NativeClass
{
private:
int AddressOfManagedHandle;
public:
static NativeClass * GetNativeClassFromHashMap(int SomeParameter)
{
// return NativeClass associated with SomeParameter from NativeClassHashMap;
}
NativeClass(int addr, int SomeParameter) : AddressOfManagedHandle(addr)
{
}
int GetAddress(){return AddressOfManagedHandle;}
void DoCalculation(){
// CALCULATIONS
}
};
public ref class ManagedClass : MarshalByRefObject
{
private:
NativeClass* _nc;
//GCHandle handle;
void FreeManagedClass()
{
Marshal::FreeHGlobal(IntPtr(_nc->GetAddress()));
//if(handle.IsAllocated)
//handle.Free();
delete _nc;
}
public:
ManagedClass()
{
IntPtr addr = (Marshal::AllocHGlobal(Marshal::Sizeof(this))); // Error
Marshal::StructureToPtr(this,addr,true);
//handle = GCHandle.Alloc(this);
//IntPtr addr = handle.ToIntPtr();
_nc = new NativeClass(addr.ToInt32());
}
~ManagedClass() {FreeManagedClass();}
!ManagedClass() {FreeManagedClass();}
int GetAddress() {return _nc->GetAddress();};
static ManagedClass^ GetManagedClass(int SomeParameter)
{
int addr = NativeClass::GetNativeClassFromHashMap(SomeParameter)->GetAddress();
//Object^obj = GCHandle::FromIntPtr(IntPtr(addr)).Target;
Object^ obj = Marshal::PtrToStructure(IntPtr(addr), ManagedClass::typeid );
return dynamic_cast<ManagedClass^>(obj);
}
};
長くなりすぎて、まだわかりにくくてすみません。