As Hans Passantwishes這裏是我的場景。我有一個混合模式的應用程序,其中本機代碼在尊重性能的同時完成所有艱苦的工作,託管代碼僅負責GUI。用戶也將通過編寫他們專有的C#代碼來參與。我有用於本地類的C++,用於GUI和用戶代碼的C#以及用於兩者之間的包裝類的C++/Cli。在我所有的C++類中,有一個做了90%的計算,並且每次都創建一個不同的參數。我們稱之爲NativeClass。有apprx。這個NativeClass的2000個實例,我必須在計算之前找到與某個參數相關的正確實例。所以我設計了一個hash_map,參數是散列碼,爲此目的。當我得到一個參數時,我在hash_map中尋找正確的實例,我找到它並調用它的一些方法。
當用戶通過編寫C#代碼來控制計算,並且這個類通過回調來執行這些代碼。這是微不足道的,但有時我需要一些關於用戶構建的.Net類的信息。所以我需要以某種方式將特定的ManagedClass附加到NativeClass。我的第一個解決方案是使用GChandle.Alloc()並傳遞句柄地址。但是有一些關於GC的concerns,它不會正常工作。 Hans建議Marshal.AllocCoTaskMem()和Marshal.StructureToPtr()在非託管內存中分配託管對象,但我相信這對於值類型類或結構體是有效的。怎麼樣ref類?我如何將引用傳遞給NativeClass,同時阻止它們被GC收集並使GC在同一時間正常工作?GCHandle,Marshal,managed and unmanaged memory:To pin or Not To Pin
下面是一些示例代碼:
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);
}
};
對不起,這是toooooo長,目前尚不清楚。
您應該使用IntPtr而不是int來存儲本機指針。否則,您的代碼可能會在64位Windows上崩潰。 – Elmue 2014-09-01 15:28:31
您不應該釋放其他課程中的內存。編寫一個調用FreeHglobal()的析構函數(finalizer)〜NativeClass()。 – Elmue 2014-09-01 15:33:35