How to properly release memory when doing custom marshaling (ICustomMarshaler) from native to managed?

最后都变了- 提交于 2019-12-23 05:16:23

问题


My main app is in C# and I'm now trying to write a DLL (for input-output) that should be portable (in C or C++ for both Windows and Linux) and accessible both from others C++ apps and from my main C# app.

Although inside my DLL I use C++ to make my life easier, I use C-style methods for the interface, i.e. I have extern "C" { /* methods */} in my headers. I thought this was better than having a C++/CLI wrapper (hope that was the right choice since I'm already far enough, but I would be glad to hear your suggestions also on this matter).

Now in my native DLL I have structs, which contain several other structs and arrays. I simplify (a lot) with the following example:

typedef struct AStructNative{
    size_t     length,
    void*      bstructs;
}AStructNative;

typedef struct BStructNative{
    int16_t    a;
    int16_t    b;
}BStructNative;

And the C# counterparts:

public class AStruct { BStruct[]  array; }
public struct BStruct { short a; short b; }

I make use of ICustomMarshaler and the AStruct (1) can be passed to the native DLL (when writing) or (2) can be got from the DLL (when reading back). I think I've been successful for case (1) (at least it works). Now, it is not clear to me the right procedure for case (2). On the native DLL I have something similar to:

void ReadAStruct(AStructNative &value)
{
    size_t length = GetArrayLength();
    BStructNative * bstructs = (BStructNative *)malloc(length * sizeof(BStructNative));
    /*fill bstructs*/
    value.length = length;
    value.bstructs = bstructs;
}

On the C# side in MarshalNativeToManaged I successfully read back the data, however my questions are:

  1. what am I supposed to do in CleanUpNativeData(IntPtr pNativeData)? A call to Marshal.FreeCoTaskMem(pNativeData) gives an exception (saying "This may be due to a corruption of the heap...")
  2. I guess I have to provide a method on the native DLL to release the memory. What is commonly done here? What is the standard considering also that the DLL should be portable and used from other C++ apps? I guess that I should not have a method like FreeAStruct(AStructNative &value) otherwise this will produce a further marshaling of the struct, hence should I do something like FreeAStruct() and keeping a pointer to allocated memory in the DLL?

来源:https://stackoverflow.com/questions/23991078/how-to-properly-release-memory-when-doing-custom-marshaling-icustommarshaler-f

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!