I would have the unmanaged code allocate the memory, then let the managed side copy it into a managed array via an IntPtr and release the allocation.
You need to first make your unmanaged function return the size of it's output array:
void archive(char * dataChr, char * outChr, int length);
Then the managed side needs to get it as an IntPtr:
class Archiver {
public static byte[] Archive(string data) {
IntPtr responsePtr = IntPtr.Zero;
int length = 0;
// Call the unmanaged function with our output params
archive(data, responsePtr, length);
byte[] responseArray;
try {
// Create an array for the response
responseArray = new byte[length];
// Copy from unmanaged into managed
Marshal.Copy(responsePtr, responseArray, 0, length);
} finally {
// Free the unmanaged memory once copied
Marshal.FreeHGlobal(responsePtr);
}
return responseArray;
}
[DllImport("Archiver.dll")]
private static extern void archive(string data, [Out]IntPtr encoded, [Out]int length);
}
You didn't specify if your data was actually a string or if you were using a stringbuffer to hold opaque binary data. If the response data is a null-terminated string then you can easily use PtrToStringUni
or PtrToStringAnsi
to get a string
instead of a simple array:
On the unmanaged side:
void archive(char * dataChr, char * outChr);
On the managed side:
class Archiver {
public static string Archive(string data) {
IntPtr responsePtr = IntPtr.Zero;
// Call the unmanaged function with our output params
archive(data, responsePtr);
string responseString;
try {
// Marshal the string from unmanaged SZ String
responseString = Marshal.PtrToStringAnsi(responsePtr);
} finally {
// Free the unmanaged memory once copied
Marshal.FreeHGlobal(responsePtr);
}
return responseString;
}
[DllImport("Archiver.dll")]
private static extern void archive(string data, [Out]IntPtr encoded);
}
NB: I didn't test any of this code, so there may be some small omissions or bugs...