I've found many ways of getting an IntPtr
from a byte[]
, all of which I could successfully pass into external unmanaged code, but only if I allocate the byte[]
on the stack. Attempting to do the same on a byte[]
instance variable, I get a null
(IntPtr.Zero
) result, no matter which method of getting an IntPtr
I choose. I haven't found any information on whether or not instance variables are treated differently than those allocated on the stack, in this case.
Here is what I would like to use to acquire a valid IntPtr
to a byte[]
instance variable:
GCHandle pinned = GCHandle.Alloc(outBytes, GCHandleType.Pinned);
IntPtr ptr = pinned.AddrOfPinnedObject();
// Always true, for reasons I'm unaware.
if (ptr == IntPtr.Zero) {}
pinned.Free();
Thanks!
The only time that GCHandle.Alloc( thing, GCHandleType.Pinned )
results in a handle to IntPtr.Zero
is when thing
is null.
Your byte array reference is null when you provide it to GCHandle.Alloc()
.
Here's where it returns zero:
public class ZeroTest
{
private byte[] someArray;
public Test()
{
this.someArray = null;
}
public void DoMarshal()
{
GCHandle handle = GCHandle.Alloc( this.someArray, GCHandleType.Pinned );
try
{
// Prints '0'.
Console.Out.WriteLine( handle.AddrOfPinnedObject().ToString() );
}
finally
{
handle.Free();
}
}
}
Here's where it returns non-zero:
public class Test
{
private byte[] someArray;
public Test()
{
this.someArray = new byte[1];
}
public void DoMarshal()
{
GCHandle handle = GCHandle.Alloc( this.someArray, GCHandleType.Pinned );
try
{
// Prints a non-zero address, like '650180924952'.
Console.Out.WriteLine( handle.AddrOfPinnedObject().ToString() );
}
finally
{
handle.Free();
}
}
}