views:

622

answers:

3
+1  Q: 

Pointer math in C#

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);
A: 

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);
Adam Tegen
+3  A: 

You should do this:

IntPtr sBuffer = new IntPtr( buffer.ToInt64() + 4 );
string s = Marshal.PtrToStringAuto( sBuffer );

So your code is 64bit safe.

Matt Ellis
A: 

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));
Adam Tegen