views:

1065

answers:

3

I have this C++ code:

extern "C" __declspec(dllexport) VOID AllocateFoo(MY_DATA_STRUCTURE** foo)
{
    *foo = new MY_DATA_STRUCTURE;

    //do stuff to foo
}

Then in C# I call the function thus:

[DllImport("MyDll.dll")]
static extern void AllocateFoo(out IntPtr pMyDataStruct);

...

MyDataStructure GetMyDataStructure()
{
    IntPtr pData;
    ManagedAllocateFooDelegate(out pData);

    MyDataStructure foo = (MyDataStructure)Marshal.PtrToStructure(pData, typeof(MyDataStructure));
    return foo;
}

Where MyDataStructure is a struct (not class) which corresponds to MY_DATA_STRUCTURE and members are marshalled appropriately.

So questions: do I need to store pData and then release it again in unmanaged code when MyDataStructure is GC'd? MSDN says for Marshal.PtrToStructure(IntPtr, Type): "Marshals data from an unmanaged block of memory to a newly allocated managed object of the specified type." In that sentence does "Marshall" mean "copy"? In which case I'd need to preserve (IntPtr pData) and then pass it to unmanaged code (in the MyDataStructure destructor) so I can do a C++ "delete"?

I've searched but I can't locate a sufficiently explicit answer for this.

+4  A: 

Yes, in this case, Marshall means copy; thus, you need to deallocate your memory in unmanaged code. All the call to PtrToStructure does is read a number of bytes indicated by the size of the destination structure 'MyDataStructure' from the memory location pointed to by pData.

The details of course depend on exactly what 'MyDataStructure' looks like (do you use any FieldOffset or StructLayout attributes in MyDataStructure) - but the end result is that the return from PtrToStructure is a copy of the data.

As GBegen points out in his answer, I didn't answer the main point of your question. Yes, you will need to delete the unmanaged copy of your structure in unmanaged code, but no, you don't need to hold onto pData - you can delete the unmanaged copy as soon as the call to PtrToStructure completes.

PS: I've edited my post to contain this information so as to consolidate the answers into one post - if anyone upvotes this answer, please upvote GBegen's answer as well for his contribution.

Erik Forbes
+5  A: 

As Erik said, the Marshal does mean copy, but I don't think he answered the main point of your question.

Do you need to hold onto the pData native pointer until the MyDataStructure is GCed? No.

Once marshaled, your MyDataStructure instance, foo, contains a copy of the structure pointed to by pData. You need not hold onto pData any longer. To avoid a memory leak, you must pass that pData into another unmanaged function that will delete it, and that can be done right after the marshaling, regardless of how long you hold on to the MyDataStructure instance.

GBegen
A: 

how do i store values in a structure ?

here is how i get the values from structure

MydatainfoArray Mydtinfo = new MydatainfoArray();

IntPtr MyinfoBuffer = IntPtr.Zero; int FIN = Marshal.SizeOf(Mydtinfo); MyinfoBuffer =
  Marshal.AllocCoTaskMem((int)FIN); Marshal.StructureToPtr(Mydtinfo, MyinfoBuffer, true);

Mydatainfo onedinfo = new Mydatainfo(); List MyinfoData = new List();

SDKRet = SDK.SDK_Get(deviceIndex, 0, MyinfoBuffer);

onedinfo = (Mydatainfo)Marshal.PtrToStructure(MyinfoBuffer, onedinfo.GetType()); MyinfoData.Add(onedinfo);

Now i have to store values in the structure. how do i do that ? please help...