问题
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:
- what am I supposed to do in
CleanUpNativeData(IntPtr pNativeData)
? A call toMarshal.FreeCoTaskMem(pNativeData)
gives an exception (saying "This may be due to a corruption of the heap...") - 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 likeFreeAStruct()
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