I allocate IntPtr pointing to an array of struct to be used with unmanaged code. I found lot of resources on this subject and here is my final method (seems to work well):
public IntPtr ArrayToPtr<T>(T[] array)
{
int size = array.Length;
int elemSize = Marshal.SizeOf(typeof(T));
IntPtr result = Marshal.AllocHGlobal(elemSize * size);
for (int i = 0; i < size; i++)
{
IntPtr ptr = new IntPtr(result.ToInt64() + elemSize * i);
Marshal.StructureToPtr(array[i], ptr, false);
}
return result;
}
Now my questions:
Same questions for an array of strings (a char** in C):
public IntPtr ArrayOfStringToPtr(string[] array)
{
int size = array.Length;
int elemSize = IntPtr.Size;
IntPtr result = Marshal.AllocHGlobal(elemSize * size);
for (int i = 0; i < size; i++)
{
IntPtr strPtr = Marshal.StringToHGlobalAnsi(array[i]);
Marshal.StructureToPtr(strPtr, new IntPtr(result.ToInt64() + elemSize * i), false);
}
return result;
}
Yes, you only need to call Marshal.FreeHGlobal(hglobal)
once you have finished using the memory.
Because you are using IntPtr
it will automatically work on x86 or x64 platforms because IntPtr
takes care of the difference in pointer size for you.
However, you shouldn't use ToInt64()
to do your pointer arithmetic.
Instead of
IntPtr ptr = new IntPtr(result.ToInt64() + elemSize * i);
Do this:
IntPtr ptr = IntPtr.Add(result, elemSize * i);