Pointer math in C#
-
03-07-2019 - |
Question
I am trying to use some pinvoke code to call a C function. The function fills a buffer with data.
The structure is set up as a DWORD for the length, followed by a string. How do I extract the string from the IntPtr?
IntPtr buffer = Marshal.AllocHGlobal(nRequiredSize);
PInvokedFunction(buffer, nRequiredSize);
string s = Marshal.PtrToStringAuto(buffer + 4); //this is an error.
Marshal.FreeHGlobal(buffer);
Solution
You should do this:
IntPtr sBuffer = new IntPtr( buffer.ToInt64() + 4 );
string s = Marshal.PtrToStringAuto( sBuffer );
So your code is 64bit safe.
OTHER TIPS
The best I could come up with was the following, though the use of the UnmanagedMemoryStream seems a bit of a hack.
IntPtr buffer = Marshal.AllocHGlobal((int)nRequiredSize);
PInvokedFunction(buffer, nRequiredSize);
UnmanagedMemoryStream memStream = new UnmanagedMemoryStream(buffer.ToPointer(), nRequiredSize);
memStream.Seek(4, SeekOrigin.Begin);
IntPtr ptr = new IntPtr(memStream.PositionPointer);
string s = Marshal.PtrToStringAuto(ptr);
Marshal.FreeHGlobal(buffer);
This seemed to work, although I think I like Matt Ellis's Answer better.
I changed the IntPtr on the [DllImport] to a byte[].
//allocate the buffer in .Net
byte[] buffer = new byte[nRequiredSize];
//call the WIN32 function, passing it the allocated buffer
PInvokedFunction(buffer);
//get the string from the 5th byte
string s = Marshal.PtrToStringAuto(Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 4));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow