With the current definition:
void get_checksum(uint cbData, out uint pcbData, byte[] pbData);
You don't need to pin pbData
. However, you'd need to pre-allocate an array for the returned the data, but you don't know the size in advance. The method will fail if the array size you pass via cbData
is not large enough, and your current method signature doesn't allow to find out the buffer size.
The original C++ declaration does allow that:
HRESULT get_checksum (
DWORD cbData,
DWORD* pcbData,
BYTE data[]
);
data [in, out] A buffer that is filled with the checksum bytes. If this parameter is NULL, then pcbData returns the number of bytes required.
So, a more efficient approach might be to declare and use it like this:
void get_checksum(
uint cbData,
out uint pcbData,
IntPtr data);
// get size
uint size;
obj.get_checksum(0, out size, IntPtr.Zero);
// get data
var buff = new byte[size];
unsafe
{
fixed (byte* p = buff)
{
uint cbData;
obj.get_checksum(size, out cbData, (IntPtr)p);
if (size != cbData)
throw new InvalidOperationException("cbData");
}
}
If you don't want (or can't) use unsafe
code, here's an alternative:
// get size
uint size;
obj.get_checksum(0, out size, IntPtr.Zero);
// get the data
byte[] buff;
var p = Marshal.AllocHGlobal((int)size);
try
{
uint cbData;
obj.get_checksum(size, out cbData, p);
if (size < cbData)
throw new InvalidOperationException("cbData");
buff = new byte[cbData];
Marshal.Copy(p, buff, 0, (int)cbData);
}
finally
{
Marshal.FreeHGlobal(p);
}