Jump to content
  • Advertisement
Sign in to follow this  
ScopeDynamo

[.net] Byte[] to Int[] / Memory allocation

This topic is 4095 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Is there no way to cast from an int[] array to a byte[] array? I've tried as, implicit and explicit casts but all fail at compile time. Also if there is a way, would casting be just a simple pointer type swap ala c++ or would it be converting each element? Which brings me to another question, What's the best method for memory allocation in c#? In C++, for something like this I'd use malloc and poke the data in directly, but in C# there's no alternative I know of. Bearing in mind I want safe code. I'm creating a byte array with the size of the number of bytes I want my memory allocation to be. Any better ways?

Share this post


Link to post
Share on other sites
Advertisement
Assuming you are using C#, the ONLY way to allocate memory safely is using the new keyword.

See the BitConverter class. You are going to need to copy each eleminate at a time, but the BitConverter class will give you a platform- and endian-agnostic conversion to bytes. You will need to perform a per element array conversion.

Share this post


Link to post
Share on other sites
Quote:

Is there no way to cast from an int[] array to a byte[] array?
I've tried as, implicit and explicit casts but all fail at compile time.


Try with System.BitConverter


int i = 56;
byte[] b = System.BitConverter(i);

Share this post


Link to post
Share on other sites
Wow, so there's no way to allocate a block of memory and access with as byte/int etc.

I.e imagine an old basic bank. Where you can poke ints/bytes/long etc into it at any position.

In C# a block of memory is either int/byte and the only way to treat it differently is to first convert it?

What I want to do is something like

public void PokeInt( int ByteIndex,int value)
{
byte[] data = new byte[1024];
byte+=byteindex; //advance the byte pointer
int[] idata = (int[]) data;
idata[0] = int;
}

Nothing like that possible in c#?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
What you want to do is an unsafe typecast, so you MUST do it in unsafe code ;)

An int[] is as related to a byte[] as a string, a delegate or a System.Windows.Forms.Form

In safe code you can only cast to types the real object type inherits from.

Share this post


Link to post
Share on other sites
You have to use an unsafe context for this type of memory manipulation.

First off, you must set "Allow Unsafe Code Blocks" in project properties.

Next, you could do something like:


public void PokeInt(int byteIndex, int byteValue)
{
byte[] data = new byte[1024];

unsafe
{
fixed (byte* bytePtr = data)
{
byte* byteIter = bytePtr + byteIndex;

byte[] intBytes = BitConverter.GetBytes(byteValue);

*(byteIter)++ = intBytes[0];
*(byteIter)++ = intBytes[1];
*(byteIter)++ = intBytes[2];
*(byteIter)++ = intBytes[3];
}
}
}


Or something like:


public void PokeInt(int byteIndex, int byteValue)
{
byte[] data = new byte[1024];

unsafe
{
fixed (byte* bytePtr = data)
{
byte* byteIter = bytePtr + byteIndex;
*((int*)byteIter) = byteValue;
}
}
}


Just depends on the syntax you prefer.


Hope that helps you!

~Graham

Share this post


Link to post
Share on other sites
You can also do somehting like this (copy, not cast):

byte[] src = new byte[5*4];
int[] tgt = new int[5];
GCHandle h = GCHandle.Alloc(tgt,GCHandleType.Pinned);
Marshal.Copy(src,0,h.AddrOfPinnedObject(),src.Length);
h.Free();

Without going unsafe. It should work in reverse too. Be aware the that the byte order may be different than you expect. With a few changes you could eaisly throw primitives and structs into byte array.

If you want to look at the same data in two different ways you can use a C# union:

[StructLayout(LayoutKind.Explicit, Size=20)]
struct IntByteUnion {
[FieldOffset(0)]unsafe fixed int[5] intData;
[FieldOffset(0)]unsafe fixed byte[20] byteData;
}

But, you must be using dotnet 2.0(for fixed arrays), know how big your data is going to be and access you data from an unsafe context using a fixed block.

If you want to allocate some unmanaged memory take a look at stackalloc, Marshal.AllocHGlobal and Marshal.AllocCoTaskMem. The last two will both execute without an unsafe context and the memory can be manipulated via Marshal in a safe context, but I am not sure what sorts of checking Marshal does and if it really makes this sort of operation 'safe'.

Share this post


Link to post
Share on other sites
I think a MemoryStream wrapped with a BinaryWriter will achieve what you're after. You use it like this:

private MemoryStream memStream;
private BinaryWriter binWriter;

public void Setup(byte[] data)
{
memStream = new MemoryStream(data);
binWriter = new BinaryWriter(memStream);
}

public void PokeInt(int byteIndex, int intValue)
{
binWriter.Seek(byteIndex, SeekOrigin.Begin);
binWriter.Write(intValue);
}



Share this post


Link to post
Share on other sites
Thanks for the help. Just to clarify, is unsafe code in a .dll result in any apps using the dll needing to be marked as allowed to run unsafe code too?

Or the memory writer idea, will that be much slower than the unsafe direct method?

Share this post


Link to post
Share on other sites
Quote:
Original post by ScopeDynamo
Thanks for the help. Just to clarify, is unsafe code in a .dll result in any apps using the dll needing to be marked as allowed to run unsafe code too?

I *think* they do, but I'm not 100% on this.

Quote:
Original post by ScopeDynamoOr the memory writer idea, will that be much slower than the unsafe direct method?

While I imagine the unsafe code would be slightly faster, I certainly wouldn't use it unless I absolutely need the extra speed. IMHO just go with the MemoryStream for now, and if you find it is causing speed problems switch over to the unsafe method. So long as you don't allow the MemoryStream or BinaryWriter to be accessed directly (ie. expose your own interface to it and not the implementation), changing it over would be very easy.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!