I have a .dll(not my own) that has a delegate. This delegate Callback function is:
"CallBackFN(ushort opCOde, IntPtr payload, uint size, uint localIP)"
How can i convert IntPtr to Byte[]? I think that payload is actually Byte[]. If it's not Byte[] and it's something else would i lose some data?
If it's a byte[] array:
byte[] managedArray = new byte[size];
Marshal.Copy(pnt, managedArray, 0, size);
If it's not byte[], the size parameter in of Marshal.Copy is the number of elements in the array, not the byte size. So, if you had an int[] array rather than a byte[] array, you would have to divide by 4 (bytes per int) to get the correct number of elements to copy, assuming your size parameter passed through the callback refers to the number of bytes.
If you need performance, use it directly:
unsafe {
byte *ptr = (byte *)buffer.ToPointer();
int offset = 0;
for (int i=0; i<height; i++)
{
for (int j=0; j<width; j++)
{
float b = (float)ptr[offset+0] / 255.0f;
float g = (float)ptr[offset+1] / 255.0f;
float r = (float)ptr[offset+2] / 255.0f;
float a = (float)ptr[offset+3] / 255.0f;
offset += 4;
UnityEngine.Color color = new UnityEngine.Color(r, g, b, a);
texture.SetPixel(j, height-i, color);
}
}
}
Have you looked into Marshal.Copy?
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.copy.aspx
According to this Stack Overflow question, you can do the following:
var byteArray = new byte[dataBlockSize];
System.Runtime.InteropServices.Marshal.Copy(payload, byteArray, 0, dataBlockSize);
Span<byte> may be a better solution as it provides most features you need from a byte array. It is faster as you won't need to allocate and copy to a new buffer and safer as you will not have to use directly the pointer.
IntPtr ptr = ... ;
int ptrLength = ...;
unsafe
{
Span<byte> byteArray = new Span<byte>(ptr.ToPointer(), ptrLength);
for (int i = 0; i < byteArray.Length; i++ )
{
// Use it as normalarray array ;
byteArray[i] = 6;
}
// You can always get a byte array . Caution, it allocates a new buffer
byte[] realByteArray = byteArray.ToArray();
}
It's included in.NET Core 2.1 and a nuget package (System.Memory) for .NET Framework 4.5 + and .NET Core 2.0 +;
You can use Marshal.Copy Method (IntPtr, Byte[], Int32, Int32)
Related
is it possible to somehow cast the type of a pointer created by the fixed() statement?
This is the situation:
I have an array of byte, which i would like to iterate through, however i would like the values to be treated as int, thus having an int* instead of a byte*.
Here's some exemplary code:
byte[] rawdata = new byte[1024];
fixed(int* ptr = rawdata) //this fails with an implicit cast error
{
for(int i = idx; i < rawdata.Length; i++)
{
//do some work here
}
}
Can this be done without having to do the cast inside the iteration?
byte[] rawdata = new byte[1024];
fixed(byte* bptr = rawdata)
{
int* ptr=(int*)bptr;
for(int i = idx; i < rawdata.Length; i++)
{
//do some work here
}
}
I believe you have to go via a byte*. For example:
using System;
class Test
{
unsafe static void Main()
{
byte[] rawData = new byte[1024];
rawData[0] = 1;
rawData[1] = 2;
fixed (byte* bytePtr = rawData)
{
int* intPtr = (int*) bytePtr;
Console.WriteLine(intPtr[0]); // Prints 513 on my box
}
}
}
Note that when iterating, you should use rawData.Length / 4, not rawData.Length if you're treating your byte array as a sequence of 32-bit values.
I found a - seemingly - more elegant and for some reason also faster way of doing this:
byte[] rawData = new byte[1024];
GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
int* iPtr = (int*)rawDataHandle.AddrOfPinnedObject().ToPointer();
int length = rawData.Length / sizeof (int);
for (int idx = 0; idx < length; idx++, iPtr++)
{
(*iPtr) = idx;
Console.WriteLine("Value of integer at pointer position: {0}", (*iPtr));
}
rawDataHandle.Free();
This way the only thing i need to do - apart from setting the correct iteration length - is increment the pointer. I compared the code with the one using the fixed statement, and this one is slightly faster.
This might be a simple one, but I can't seem to find an easy way to do it. I need to save an array of 84 uint's into an SQL database's BINARY field. So I'm using the following lines in my C# ASP.NET project:
//This is what I have
uint[] uintArray;
//I need to convert from uint[] to byte[]
byte[] byteArray = ???
cmd.Parameters.Add("#myBindaryData", SqlDbType.Binary).Value = byteArray;
So how do you convert from uint[] to byte[]?
How about:
byte[] byteArray = uintArray.SelectMany(BitConverter.GetBytes).ToArray();
This'll do what you want, in little-endian format...
You can use System.Buffer.BlockCopy to do this:
byte[] byteArray = new byte[uintArray.Length * 4];
Buffer.BlockCopy(uintArray, 0, byteArray, 0, uintArray.Length * 4];
http://msdn.microsoft.com/en-us/library/system.buffer.blockcopy.aspx
This will be much more efficient than using a for loop or some similar construct. It directly copies the bytes from the first array to the second.
To convert back just do the same thing in reverse.
There is no built-in conversion function to do this. Because of the way arrays work, a whole new array will need to be allocated and its values filled-in. You will probably just have to write that yourself. You can use the System.BitConverter.GetBytes(uint) function to do some of the work, and then copy the resulting values into the final byte[].
Here's a function that will do the conversion in little-endian format:
private static byte[] ConvertUInt32ArrayToByteArray(uint[] value)
{
const int bytesPerUInt32 = 4;
byte[] result = new byte[value.Length * bytesPerUInt32];
for (int index = 0; index < value.Length; index++)
{
byte[] partialResult = System.BitConverter.GetBytes(value[index]);
for (int indexTwo = 0; indexTwo < partialResult.Length; indexTwo++)
result[index * bytesPerUInt32 + indexTwo] = partialResult[indexTwo];
}
return result;
}
byte[] byteArray = Array.ConvertAll<uint, byte>(
uintArray,
new Converter<uint, byte>(
delegate(uint u) { return (byte)u; }
));
Heed advice from #liho1eye, make sure your uints really fit into bytes, otherwise you're losing data.
If you need all the bits from each uint, you're gonna to have to make an appropriately sized byte[] and copy each uint into the four bytes it represents.
Something like this ought to work:
uint[] uintArray;
//I need to convert from uint[] to byte[]
byte[] byteArray = new byte[uintArray.Length * sizeof(uint)];
for (int i = 0; i < uintArray.Length; i++)
{
byte[] barray = System.BitConverter.GetBytes(uintArray[i]);
for (int j = 0; j < barray.Length; j++)
{
byteArray[i * sizeof(uint) + j] = barray[j];
}
}
cmd.Parameters.Add("#myBindaryData", SqlDbType.Binary).Value = byteArray;
How to convert an int[,] to byte[] in C#?
Some code will be appreciated
EDIT:
I need a function to perform the following:
byte[] FuncName (int[,] Input)
Since there is very little detail in your question, I can only guess what you're trying to do... Assuming you want to "flatten" a 2D array of ints into a 1D array of bytes, you can do something like that :
byte[] Flatten(int[,] input)
{
return input.Cast<int>().Select(i => (byte)i).ToArray();
}
Note the call to Cast : that's because multidimensional arrays implement IEnumerable but not IEnumerable<T>
It seem that you are writing the types wrong, but here is what you might be looking for:
byte[] FuncName (int[,] input)
{
byte[] byteArray = new byte[input.Length];
int idx = 0;
foreach (int v in input) {
byteArray[idx++] = (byte)v;
}
return byteArray;
}
Here's an implementation that assumes you are attempting serialization; no idea if this is what you want, though; it prefixes the dimensions, then each cell using basic encoding:
public byte[] Encode(int[,] input)
{
int d0 = input.GetLength(0), d1 = input.GetLength(1);
byte[] raw = new byte[((d0 * d1) + 2) * 4];
Buffer.BlockCopy(BitConverter.GetBytes(d0), 0, raw, 0, 4);
Buffer.BlockCopy(BitConverter.GetBytes(d1), 0, raw, 4, 4);
int offset = 8;
for(int i0 = 0 ; i0 < d0 ; i0++)
for (int i1 = 0; i1 < d1; i1++)
{
Buffer.BlockCopy(BitConverter.GetBytes(input[i0,i1]), 0,
raw, offset, 4);
offset += 4;
}
return raw;
}
The BitConverter converts primitive types to byte arrays:
byte[] myByteArray = System.BitConverter.GetBytes(myInt);
You appear to want a 2 dimensional array of ints to be converted to bytes. Combine the BitConverter with the requisite loop construct (e.g foreach) and whatever logic you want to combine the array dimensions.
I want to do the equivalent of this:
byte[] byteArray;
enum commands : byte {one, two};
commands content = one;
byteArray = (byte*)&content;
yes, it's a byte now, but consider I want to change it in the future? how do I make byteArray contain content? (I don't care to copy it).
To convert any value types (not just primitive types) to byte arrays and vice versa:
public T FromByteArray<T>(byte[] rawValue)
{
GCHandle handle = GCHandle.Alloc(rawValue, GCHandleType.Pinned);
T structure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return structure;
}
public byte[] ToByteArray(object value, int maxLength)
{
int rawsize = Marshal.SizeOf(value);
byte[] rawdata = new byte[rawsize];
GCHandle handle =
GCHandle.Alloc(rawdata,
GCHandleType.Pinned);
Marshal.StructureToPtr(value,
handle.AddrOfPinnedObject(),
false);
handle.Free();
if (maxLength < rawdata.Length) {
byte[] temp = new byte[maxLength];
Array.Copy(rawdata, temp, maxLength);
return temp;
} else {
return rawdata;
}
}
The BitConverter class might be what you are looking for. Example:
int input = 123;
byte[] output = BitConverter.GetBytes(input);
If your enum was known to be an Int32 derived type, you could simply cast its values first:
BitConverter.GetBytes((int)commands.one);
You can use the BitConverter.GetBytes method to do this.
For anyone who's interested in how it works without using BitConverter you can do it like this:
// Convert double to byte[]
public unsafe byte[] pack(double d) {
byte[] packed = new byte[8]; // There are 8 bytes in a double
void* ptr = &d; // Get a reference to the memory containing the double
for (int i = 0; i < 8; i++) { // Each one of the 8 bytes needs to be added to the byte array
packed[i] = (byte)(*(UInt64 *)ptr >> (8 * i)); // Bit shift so that each chunk of 8 bits (1 byte) is cast as a byte and added to array
}
return packed;
}
// Convert byte[] to double
public unsafe double unpackDouble(byte[] data) {
double unpacked = 0.0; // Prepare a chunk of memory ready for the double
void* ptr = &unpacked; // Reference the double memory
for (int i = 0; i < data.Length; i++) {
*(UInt64 *)ptr |= ((UInt64)data[i] << (8 * i)); // Get the bits into the right place and OR into the double
}
return unpacked;
}
In reality it's much easier and safer to use BitConverter but it's fun to know!
I would like to get a byte[] from a float[] as quickly as possible, without looping through the whole array (via a cast, probably). Unsafe code is fine. Thanks!
I am looking for a byte array 4 time longer than the float array (the dimension of the byte array will be 4 times that of the float array, since each float is composed of 4 bytes). I'll pass this to a BinaryWriter.
EDIT:
To those critics screaming "premature optimization":
I have benchmarked this using ANTS profiler before I optimized. There was a significant speed increase because the file has a write-through cache and the float array is exactly sized to match the sector size on the disk. The binary writer wraps a file handle created with pinvoke'd win32 API. The optimization occurs since this lessens the number of function calls.
And, with regard to memory, this application creates massive caches which use plenty of memory. I can allocate the byte buffer once and re-use it many times--the double memory usage in this particular instance amounts to a roundoff error in the overall memory consumption of the app.
So I guess the lesson here is not to make premature assumptions ;)
There is a dirty fast (not unsafe code) way of doing this:
[StructLayout(LayoutKind.Explicit)]
struct BytetoDoubleConverter
{
[FieldOffset(0)]
public Byte[] Bytes;
[FieldOffset(0)]
public Double[] Doubles;
}
//...
static Double Sum(byte[] data)
{
BytetoDoubleConverter convert = new BytetoDoubleConverter { Bytes = data };
Double result = 0;
for (int i = 0; i < convert.Doubles.Length / sizeof(Double); i++)
{
result += convert.Doubles[i];
}
return result;
}
This will work, but I'm not sure of the support on Mono or newer versions of the CLR. The only strange thing is that the array.Length is the bytes length. This can be explained because it looks at the array length stored with the array, and because this array was a byte array that length will still be in byte length. The indexer does think about the Double being eight bytes large so no calculation is necessary there.
I've looked for it some more, and it's actually described on MSDN, How to: Create a C/C++ Union by Using Attributes (C# and Visual Basic), so chances are this will be supported in future versions. I am not sure about Mono though.
Premature optimization is the root of all evil! #Vlad's suggestion to iterate over each float is a much more reasonable answer than switching to a byte[]. Take the following table of runtimes for increasing numbers of elements (average of 50 runs):
Elements BinaryWriter(float) BinaryWriter(byte[])
-----------------------------------------------------------
10 8.72ms 8.76ms
100 8.94ms 8.82ms
1000 10.32ms 9.06ms
10000 32.56ms 10.34ms
100000 213.28ms 739.90ms
1000000 1955.92ms 10668.56ms
There is little difference between the two for small numbers of elements. Once you get into the huge number of elements range, the time spent copying from the float[] to the byte[] far outweighs the benefits.
So go with what is simple:
float[] data = new float[...];
foreach(float value in data)
{
writer.Write(value);
}
There is a way which avoids memory copying and iteration.
You can use a really ugly hack to temporary change your array to another type using (unsafe) memory manipulation.
I tested this hack in both 32 & 64 bit OS, so it should be portable.
The source + sample usage is maintained at https://gist.github.com/1050703 , but for your convenience I'll paste it here as well:
public static unsafe class FastArraySerializer
{
[StructLayout(LayoutKind.Explicit)]
private struct Union
{
[FieldOffset(0)] public byte[] bytes;
[FieldOffset(0)] public float[] floats;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct ArrayHeader
{
public UIntPtr type;
public UIntPtr length;
}
private static readonly UIntPtr BYTE_ARRAY_TYPE;
private static readonly UIntPtr FLOAT_ARRAY_TYPE;
static FastArraySerializer()
{
fixed (void* pBytes = new byte[1])
fixed (void* pFloats = new float[1])
{
BYTE_ARRAY_TYPE = getHeader(pBytes)->type;
FLOAT_ARRAY_TYPE = getHeader(pFloats)->type;
}
}
public static void AsByteArray(this float[] floats, Action<byte[]> action)
{
if (floats.handleNullOrEmptyArray(action))
return;
var union = new Union {floats = floats};
union.floats.toByteArray();
try
{
action(union.bytes);
}
finally
{
union.bytes.toFloatArray();
}
}
public static void AsFloatArray(this byte[] bytes, Action<float[]> action)
{
if (bytes.handleNullOrEmptyArray(action))
return;
var union = new Union {bytes = bytes};
union.bytes.toFloatArray();
try
{
action(union.floats);
}
finally
{
union.floats.toByteArray();
}
}
public static bool handleNullOrEmptyArray<TSrc,TDst>(this TSrc[] array, Action<TDst[]> action)
{
if (array == null)
{
action(null);
return true;
}
if (array.Length == 0)
{
action(new TDst[0]);
return true;
}
return false;
}
private static ArrayHeader* getHeader(void* pBytes)
{
return (ArrayHeader*)pBytes - 1;
}
private static void toFloatArray(this byte[] bytes)
{
fixed (void* pArray = bytes)
{
var pHeader = getHeader(pArray);
pHeader->type = FLOAT_ARRAY_TYPE;
pHeader->length = (UIntPtr)(bytes.Length / sizeof(float));
}
}
private static void toByteArray(this float[] floats)
{
fixed(void* pArray = floats)
{
var pHeader = getHeader(pArray);
pHeader->type = BYTE_ARRAY_TYPE;
pHeader->length = (UIntPtr)(floats.Length * sizeof(float));
}
}
}
And the usage is:
var floats = new float[] {0, 1, 0, 1};
floats.AsByteArray(bytes =>
{
foreach (var b in bytes)
{
Console.WriteLine(b);
}
});
If you do not want any conversion to happen, I would suggest Buffer.BlockCopy().
public static void BlockCopy(
Array src,
int srcOffset,
Array dst,
int dstOffset,
int count
)
For example:
float[] floatArray = new float[1000];
byte[] byteArray = new byte[floatArray.Length * 4];
Buffer.BlockCopy(floatArray, 0, byteArray, 0, byteArray.Length);
You're better-off letting the BinaryWriter do this for you. There's going to be iteration over your entire set of data regardless of which method you use, so there's no point in playing with bytes.
Although you can obtain a byte* pointer using unsafe and fixed, you cannot convert the byte* to byte[] in order for the writer to accept it as a parameter without performing data copy. Which you do not want to do as it will double your memory footprint and add an extra iteration over the inevitable iteration that needs to be performed in order to output the data to disk.
Instead, you are still better off iterating over the array of floats and writing each float to the writer individually, using the Write(double) method. It will still be fast because of buffering inside the writer. See sixlettervariables's numbers.
Using the new Span<> in .Net Core 2.1 or later...
byte[] byteArray2 = MemoryMarshal.Cast<float, byte>(floatArray).ToArray();
Or, if Span can be used instead, then a direct reinterpret cast can be done: (very fast - zero copying)
Span<byte> byteArray3 = MemoryMarshal.Cast<float, byte>(floatArray);
// with span we can get a byte, set a byte, iterate, and more.
byte someByte = byteSpan[2];
byteSpan[2] = 33;
I did some crude benchmarks. The time taken for each is in the comments. [release/no debugger/x64]
float[] floatArray = new float[100];
for (int i = 0; i < 100; i++) floatArray[i] = i * 7.7777f;
Stopwatch start = Stopwatch.StartNew();
for (int j = 0; j < 100; j++)
{
start.Restart();
for (int k = 0; k < 1000; k++)
{
Span<byte> byteSpan = MemoryMarshal.Cast<float, byte>(floatArray);
}
long timeTaken1 = start.ElapsedTicks; ////// 0 ticks //////
start.Restart();
for (int k = 0; k < 1000; k++)
{
byte[] byteArray2 = MemoryMarshal.Cast<float, byte>(floatArray).ToArray();
}
long timeTaken2 = start.ElapsedTicks; ////// 26 ticks //////
start.Restart();
for (int k = 0; k < 1000; k++)
{
byte[] byteArray = new byte[sizeof(float) * floatArray.Length];
for (int i = 0; i < floatArray.Length; i++)
BitConverter.GetBytes(floatArray[i]).CopyTo(byteArray, i * sizeof(float));
}
long timeTaken3 = start.ElapsedTicks; ////// 1310 ticks //////
start.Restart();
for (int k = 0; k < 1000; k++)
{
byte[] byteArray = new byte[sizeof(float) * floatArray.Length];
Buffer.BlockCopy(floatArray, 0, byteArray, 0, byteArray.Length);
}
long timeTaken4 = start.ElapsedTicks; ////// 33 ticks //////
start.Restart();
for (int k = 0; k < 1000; k++)
{
byte[] byteArray = new byte[sizeof(float) * floatArray.Length];
MemoryStream memStream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(memStream);
foreach (float value in floatArray)
writer.Write(value);
writer.Close();
}
long timeTaken5 = start.ElapsedTicks; ////// 1080 ticks //////
Console.WriteLine($"{timeTaken1/10,6} {timeTaken2 / 10,6} {timeTaken3 / 10,6} {timeTaken4 / 10,6} {timeTaken5 / 10,6} ");
}
We have a class called LudicrousSpeedSerialization and it contains the following unsafe method:
static public byte[] ConvertFloatsToBytes(float[] data)
{
int n = data.Length;
byte[] ret = new byte[n * sizeof(float)];
if (n == 0) return ret;
unsafe
{
fixed (byte* pByteArray = &ret[0])
{
float* pFloatArray = (float*)pByteArray;
for (int i = 0; i < n; i++)
{
pFloatArray[i] = data[i];
}
}
}
return ret;
}
Although it basically does do a for loop behind the scenes, it does do the job in one line
byte[] byteArray = floatArray.Select(
f=>System.BitConverter.GetBytes(f)).Aggregate(
(bytes, f) => {List<byte> temp = bytes.ToList(); temp.AddRange(f); return temp.ToArray(); });