Can someone explain what exactly is happening at a low level / memory management perspective on the 2 C# lines in "Main" in the following?
C++ Code (unmanaged):
#define DLLEXPORT extern "C" __declspec(dllexport)
DLLEXPORT MyClass* MyClass_MyClass()
{
return new MyClass();
}
DLLEXPORT void MyClass_setName(MyClass* myClass, const char* name)
{
myClass->setName(name);
}
MyClass::MyClass()
{
_name.clear();
}
void MyClass::setName(const char* name)
{
_name.setCString(name, NAME_MAX_BYTES);
}
C# Code:
[DllImport(@"lib.dll")]
private static extern IntPtr MyClass_MyClass();
[DllImport(@"lib.dll")]
public static extern void MyClass_setName(
IntPtr myClass,
[System.Runtime.InteropServices.InAttribute()]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
string name);
public static void Main(string[] args)
{
var myClass = MyClass_MyClass();
MyClass_setName(myClass , "Test Name");
}
Specifically, I'm wondering how does .NET know much space to allocate for "myClass"? It's got to be doing some kind of "Marshal.AllocHGlobal(SIZE)" in the background, right? What happens if more space is needed (I set a name?)? Also, is there any risk of garbage collection coming around and moving memory around and messing up my "IntPtr myClass" ?
.NET knows nothing about MyClass
type, it only stores a pointer to it. Size of the pointer is always known and fixed - 4 bytes for 32bit processes and 8 bytes for 64bit processes. All memory allocation and management in this particular case happens in unmanaged C++ code here:
return new MyClass();
and here:
myClass->setName(name);
It's up to this C++ DLL to decide how to allocate/free/manage memory, C# code will just call imported functions of this DLL.
No garbage collection will be performed on your unmanaged object and you'll need to provide additional (unmanaged) method to release it to avoid memory leak.