The C++ code increments the pointer like this:
++results;
That increments the address by sizeof(*results)
because that is how C++ pointer arithmetic works. So, suppose that sizeof(*results)
is equal to 4, as would be the case on a 32 bit machine. Then ++results
will increment the address by 4.
Now, your C# code is different. The pointer is untyped and the compiler knows nothing about the underlying array element type. So your code
arrayPtr = new IntPtr(arrayPtr.ToInt64() + 1);
increments the address by 1. Instead you need to supply the missing type information. Like this:
arrayPtr = new IntPtr(arrayPtr.ToInt64() + IntPtr.Size);
On top of that, your loop is implemented incorrectly. You fail to update ptr
at the correct time. It should be:
public static IEnumerable<string> MarshalStringArray(IntPtr arrayPtr)
{
if (arrayPtr != IntPtr.Zero)
{
IntPtr ptr = Marshal.ReadIntPtr(arrayPtr);
while (ptr != IntPtr.Zero)
{
string key = Marshal.PtrToStringAnsi(ptr);
yield return key;
arrayPtr = new IntPtr(arrayPtr.ToInt64() + IntPtr.Size);
ptr = Marshal.ReadIntPtr(arrayPtr);
}
}
}
You might prefer to re-cast the method so that the code that it contains only a single call to Marshal.ReadIntPtr
.
One final point. The C++ function looks like it might be using the cdecl
calling convention. You should check what the definition of SWDLLEXPORT
is. Your p/invoke is only correct if SWDLLEXPORT
specifies __stdcall
.