从原生到托管执行自定义编组(ICustomMarshaler)时如何正确释放内存?

我的主要应用程序是在C#中,我现在正在尝试编写一个DLL(用于输入输出),它应该是可移植的(在C或C ++中用于Windows和Linux),并且可以从其他C ++应用程序和我的主要C#应用程序访问。

虽然在我的DLL中我使用C ++来使我的生活更轻松,但我在界面中使用C风格的方法,即我的标题中有外部的“C”{/ *方法* /}。 我认为这比使用C ++ / CLI包装更好(希望这是正确的选择,因为我已经足够了,但我很高兴听到你对这个问题的建议)。

现在在我的本机DLL中,我有结构,其中包含其他几个结构和数组。 我通过以下示例简化(很多):

typedef struct AStructNative{ size_t length, void* bstructs; }AStructNative; typedef struct BStructNative{ int16_t a; int16_t b; }BStructNative; 

和C#同行:

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

我使用ICustomMarshalerAStruct (1)可以传递给本机DLL(写入时)或(2)可以从DLL获取(回读时)。 我认为我在案例(1)中取得了成功(至少它有效)。 现在,我不清楚案例(2)的正确程序。 在本机DLL上,我有类似于:

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

MarshalNativeToManaged的C#端我成功读回了数据,但我的问题是:

  1. 我应该在CleanUpNativeData(IntPtr pNativeData)CleanUpNativeData(IntPtr pNativeData)什么? 对Marshal.FreeCoTaskMem(pNativeData)调用给出了一个exception(说“这可能是由于堆的损坏…”)
  2. 我想我必须在本机DLL上提供一个方法来释放内存。 这里常见的是什么? 考虑到DLL应该是可移植的并且可以从其他C ++应用程序使用,标准是什么? 我想我不应该有像FreeAStruct(AStructNative &value)这样的方法,否则这将产生结构的进一步封送,因此我应该做一些类似FreeAStruct()并保持指向DLL中已分配内存的指针?