How to Copy like C++?


S

Sharon

Hello Gurus,

I have a function that copy data from byte[] to class as follow:

public static void CopyByteToHeader(Header target, byte[] source)
{
ntPtr pHeaderTarget = Marshal.AllocHGlobal(HEADER_SIZE);
arshal.Copy(source, 0, pHeaderTarget, HEADER_SIZE);
arshal.PtrToStructure(pHeaderTarget, target);
}

public const int HEADER_SIZE = 9;

[StructLayout(LayoutKind.Sequential)]
public class Header
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public byte[] m_type;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] m_lMsgIndex;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] m_lLength;
}

The function works fine. BUT:
This function is executed many times, so it makes a lot of memory copeing.

I want to optimize it doing like in C++:
Public CPP_CopyByteToHeader(Header* target, byte* source)
{
target = (Header*)source
}

This way I’m avoiding the copy.

But is C# I tried:

public static void CopyByteToHeader(Header target, byte[] source)
{
unsafe
{
fixed (byte* pSource = (byte[])source)
{
// Now I need the pointer for the target.
// But I can’t find how to!
}
}
}

As you can see its incomplete. I need to get a pointer to the target.

Can anybody show me how can I do the coply like, like it’s done in the C++
above?
 
Ad

Advertisements

J

Jesse Houwing

* Sharon wrote, On 20-10-2009 10:41:
Hello Gurus,

I have a function that copy data from byte[] to class as follow:

public static void CopyByteToHeader(Header target, byte[] source)
{
ntPtr pHeaderTarget = Marshal.AllocHGlobal(HEADER_SIZE);
arshal.Copy(source, 0, pHeaderTarget, HEADER_SIZE);
arshal.PtrToStructure(pHeaderTarget, target);
}

public const int HEADER_SIZE = 9;

[StructLayout(LayoutKind.Sequential)]
public class Header
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public byte[] m_type;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] m_lMsgIndex;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] m_lLength;
}

The function works fine. BUT:
This function is executed many times, so it makes a lot of memory copeing.

I want to optimize it doing like in C++:
Public CPP_CopyByteToHeader(Header* target, byte* source)
{
target = (Header*)source
}

This way I’m avoiding the copy.

But is C# I tried:

public static void CopyByteToHeader(Header target, byte[] source)
{
unsafe
{
fixed (byte* pSource = (byte[])source)
{
// Now I need the pointer for the target.
// But I can’t find how to!
}
}
}

As you can see its incomplete. I need to get a pointer to the target.

Can anybody show me how can I do the coply like, like it’s done in the C++
above?

Why not use the ref keyword on the byte[] source and forget about the
whole fixed business altogether?

Jesse
 
Ad

Advertisements

P

Peter Duniho

Sharon said:
[...]
I want to optimize it doing like in C++:
Public CPP_CopyByteToHeader(Header* target, byte* source)
{
target = (Header*)source
}

That C++ function doesn't do anything. Perhaps you meant "Header
**target" and "*target = (Header *)source"?
This way I’m avoiding the copy.

That's true. But if the caller discards the byte array that "source"
points to, you're in a world of hurt.
But is C# I tried:

public static void CopyByteToHeader(Header target, byte[] source)
{
unsafe
{
fixed (byte* pSource = (byte[])source)
{
// Now I need the pointer for the target.
// But I can’t find how to!
}
}
}

If you write the _entire_ thing as unsafe code, always dereferencing the
data via a pointer to your structure, it could work. Otherwise,
no...you simply can't do that in C#. Managed types and pointers are
completely different.

For what it's worth, you should understand that the "StructLayout"
attribute doesn't actually force a particular layout for the managed
type. It's used for marshaling only, to indicate how the structure
should look to unmanaged code.

Anyway...

As with the previous question, IMHO you should not be using the
low-level stuff at all. Just copy the bytes and forget the marshaling
altogether:

void CopyByteToHeader(Header target, byte[] source)
{
target.m_type = new byte[1];
Array.Copy(source, 0, target.m_type, 0, 1);
target.m_lMsgIndex = new byte[4];
Array.Copy(source, 1, target.m_lMsgIndex, 0, 4);
target.m_lLength = new byte[4];
Array.Copy(source, 5, target.m_lLength, 0, 4);
}

Though, frankly...storing that data as byte[] in your Header class
doesn't make any sense to me. IMHO, what you really ought to be doing
is just going ahead and converting the bytes to their appropriate
values, and storing them as that. In other words, all three fields wind
up being "int" fields instead of "byte[]" and are the actual values of
interest.

After all, if you ever expect to use the data as anything other than
bytes, you'll have to do that conversion eventually anyway. And if you
don't ever expect to use the data as anything other than bytes, there's
really no point in chopping up the original byte[] in the first place.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top