Marshal.Copy

  • Thread starter Thread starter clawton
  • Start date Start date
C

clawton

Hi All,

With the simple code below I get an exception on the last line of code...
Just trying to figure out some marshalling stuff...but I'm stuck...
Ultimately, the source pointer is data created in a DLL called by p/Invoke
and I need to get the data out of it into some structs.

Any help pointing out what I'm doing wrong here would be greatly appriciated!
Thanks in advance!
Chris

----------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace CopyTest
{
class Program
{
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct foo
{
public int x;
public double y;
};


static void Main(string[] args)
{


foo f = new foo();
f.x = 217;
f.y = -999.0;


IntPtr srcptr = Marshal.AllocHGlobal(Marshal.SizeOf(f));
Marshal.StructureToPtr(f, srcptr, true);

IntPtr[] one = new IntPtr[1];

Marshal.Copy(srcptr, one, 0, 1);

foo dest = (foo)Marshal.PtrToStructure(one[0], typeof(foo));
}
}
}
 
clawton said:
With the simple code below I get an exception on the last line of code...
Just trying to figure out some marshalling stuff...but I'm stuck...
Ultimately, the source pointer is data created in a DLL called by p/Invoke
and I need to get the data out of it into some structs.

Any help pointing out what I'm doing wrong here would be greatly appriciated!

Your problem is actually in the Marshal.Copy.
IntPtr srcptr = Marshal.AllocHGlobal(Marshal.SizeOf(f));
Marshal.StructureToPtr(f, srcptr, true);

IntPtr[] one = new IntPtr[1];

Marshal.Copy(srcptr, one, 0, 1);

That doesn't do what you think it does. What it actually does is copy 4
bytes from the memory that srcptr POINTS TO, not the CONTENTS of srcptr.
This would have been obvious if you had done a minimum of debugging:

System.Console.WriteLine( srcptr );
System.Console.WriteLine( one[0] );

You would see that srcptr contains an address, but one[0] contains 217,
which happens to be the value you initialized into foo.x.

In this case, you would just do this instead:
one[0] = srcptr;
 
Yeah, I figured it out a few minutes after I posted!
For some reason, I got it stuck in my head that it should be the contents
and just couldn't get past it...argh... :(

Thanks for the reply.
Chris


Tim Roberts said:
clawton said:
With the simple code below I get an exception on the last line of code...
Just trying to figure out some marshalling stuff...but I'm stuck...
Ultimately, the source pointer is data created in a DLL called by p/Invoke
and I need to get the data out of it into some structs.

Any help pointing out what I'm doing wrong here would be greatly appriciated!

Your problem is actually in the Marshal.Copy.
IntPtr srcptr = Marshal.AllocHGlobal(Marshal.SizeOf(f));
Marshal.StructureToPtr(f, srcptr, true);

IntPtr[] one = new IntPtr[1];

Marshal.Copy(srcptr, one, 0, 1);

That doesn't do what you think it does. What it actually does is copy 4
bytes from the memory that srcptr POINTS TO, not the CONTENTS of srcptr.
This would have been obvious if you had done a minimum of debugging:

System.Console.WriteLine( srcptr );
System.Console.WriteLine( one[0] );

You would see that srcptr contains an address, but one[0] contains 217,
which happens to be the value you initialized into foo.x.

In this case, you would just do this instead:
one[0] = srcptr;
 
Back
Top