[Mono-list] Deep Marshaling
Jonathan Pryor
jonpryor at vt.edu
Sun Oct 23 21:25:08 EDT 2005
On Sun, 2005-10-23 at 21:09 +0200, Giuseppe Greco wrote:
> Another alternative would be the following:
>
> [StructLayout(LayoutKind.Sequential)]
> internal struct MyStruct
> {
> public int Id;
> public unsafe byte* Data;
> }
>
> public unsafe void FillMyStruct(string s)
> {
...
> pMyStruct->Data = pData + sizeof(int);
> UnsafeCopy(
> pData, 0, // source buffer
> pMyStruct->Data, 0, // destination buffer
> data.Length); // number of bytes to copy
> }
> }
>
> public static unsafe void UnsafeCopy(
> byte* pSource, int sourceOffset,
> byte* pDest, int destOffset, int count)
> {
> byte* ps = pSource + sourceOffset;
> byte* pd = pDest + destOffset;
...
> int c = count / sizeof(long);
> for (int i = 0 ; i < c; i++) {
> *((long*)pd) = *((long*)ps);
> pd += sizeof(long);
> ps += sizeof(long);
> }
...
> That works fine and performance is quite good. Of course,
> the method UnsafeCopy() is really 'unsafe', but it defined
> in an internal class...
Are you sure this works fine? The source and destination buffers passed
to UnsafeCopy() overlap, and not in a good way:
| 00 04 08 0C 0F ...
^ ^
| pMyStruct->Data (destination)
pData (source)
>From my reading of UnsafeCopy(), it will copy data.Length bytes from
source to dest in a "left-to-right" fashion. Which means that once you
copy more than 4 bytes, you've overwritten the data you're supposed to
be copying...
What you really need is a std::copy_backward() implementation, copying
in a right-to-left fashion. That way your source buffer won't be
overwritten before it's needed...
See also the difference between memcpy(3) (which doesn't handle
overlapping buffers) and memmove(3) (which does).
- Jon
More information about the Mono-list
mailing list