Standard C++ things (like std::map
) and managed objects do not mix out of the box. It is however possible by using GCHandle to get an intptr_t that represents a managed object and keeps it from getting garbage collected.
intptr_t GetHandle(System::Object^ obj) {
auto gch = System::Runtime::InteropServices::GCHandle::Alloc(obj);
auto ip = System::Runtime::InteropServices::GCHandle::ToIntPtr(gch);
return static_cast<intptr_t>(ip);
}
Now you have an intptr_t that represents a your object and can be freely used with native C++ code. std::map<std::string, intptr_t>
To get your object from the intptr_t:
System::IO::StreamWriter^ ToStreamWriter(intptr_t h) {
auto gch = System::Runtime::InteropServices::GCHandle::FromIntPtr(static_cast<System::IntPtr>(h));
return safe_cast<System::IO::StreamWriter^>(gch.Target);
}
The intptr_t value represents a resource the needs to be freed so it should ideally be kept in an RAII object whose destructor will convert it back to a GCHandle (see above) and Free() that. If you don't do that then the StreamWriter object will never be garbage collected and you have a heap leak.
void FreeHandle(intptr_t h) {
auto gch = System::Runtime::InteropServices::GCHandle::FromIntPtr(static_cast<System::IntPtr>(h));
gch.Free();
}
I made a whole template library to do this kind of stuff so I can use managed objects freely in native code. I like this kind of thing but I don't necessarily recommend it. I've never seen it done by anyone else, but it does work nicely once you build good tools for it.