Как Ганс Пассант желает вот мой сценарий.У меня есть приложение в смешанном режиме, в котором нативный код выполняет всю тяжелую работу, сохраняя при этом производительность, а управляемый код отвечает только за графический интерфейс.Также пользователи будут участвовать, написав свой собственный код C #.У меня есть C ++ для нативных классов, C # для GUI и пользовательского кода и C ++ / Cli для классов-оболочек между ними.Среди всех моих классов C ++ есть один, который выполняет 90% вычислений и каждый раз создает новый параметр.Давайте назовем это NativeClass.Есть ок.2000 экземпляров этого NativeClass, и я должен найти правильный экземпляр, связанный с каким-либо параметром, прежде чем он выполнит вычисление.Поэтому для этой цели я разработал hash_map с параметрами, являющимися хеш-кодом.Когда я получаю параметр, я ищу нужный экземпляр в hash_map, нахожу его и вызываю некоторые из его методов.
Когда пользователи выполняют вычисления, написав код C #, и этот класс выполняет эти коды с помощью обратных вызовов.Это тривиально, но иногда мне нужна информация о классах .Net, созданных пользователями.Поэтому мне нужно каким-то образом прикрепить этот конкретный ManagedClass к NativeClass.Моим первым решением является использование GChandle.Alloc () и передача адреса дескрипторов.Но есть некоторые опасения относительно GC, что он не будет выполнять свою работу должным образом.Ганс рекомендовал Marshal.AllocCoTaskMem () и Marshal.StructureToPtr () для выделения управляемых объектов в неуправляемой памяти, однако я считаю, что это справедливо для классов или структур типов значений.Как насчет реф классов?Как я могу передать ссылку на NativeClass, не позволяя им собирать GC и одновременно заставить 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);
}
};
Извините, что онслишком долго и все еще не ясно.