Unsafe conversion to given pointer in buffer - c#

I am trying to figure out how to get this method to start at a index being ptr instead of overwriting from 0 - 8 bytes. Also if anyone knows how to make this work with Big / Little edian machines due to being networked, that would be awesome.
private byte[] buffer = new byte[30];
private int ptr = 0;
unsafe void GetBytes(ulong value)
{
fixed (byte* b = buffer) //start at buffer[ptr]
*((int*)b) = *(int*)&value;
ptr += 8;
}
I figured out how to make a pointer to the ptr via the following
private byte[] buffer = new byte[30];
private int ptr = 0;
unsafe void GetBytes(ulong value)
{
fixed (byte* b = &buffer[ptr]) //start at buffer[ptr]
*((int*)b) = *(int*)&value;
ptr += 8;
}

You can convert endianness easily:
using System.Buffers.Binary;
if (!BitConverter.IsLittleEndian)
{
value = BinaryPrimitives.ReverseEndianness(value);
}
I would prefer to use Span which will be safer and easier to read:
using System.Buffers.Binary;
Span<byte> span = buffer;
BinaryPrimitives.WriteUInt64LittleEndian(span.Slice(ptr), value);
If you want to use your system's endianness rather than something explicit, you can do that too:
using System.Runtime.InteropServices;
Span<byte> span = buffer;
MemoryMarshal.Write(span.Slice(ptr), value);
Edit for non-Core:
You can use HostToNetworkOrder to convert integers to big endian prior to writing to your pointer.

Related

Delphi convert from c#

i really need your help to port this c# code to Delphi one :
public unsafe byte[] Encode(byte[] inputPcmSamples, int sampleLength, out int encodedLength)
{
if (disposed)
throw new ObjectDisposedException("OpusEncoder");
int frames = FrameCount(inputPcmSamples);
IntPtr encodedPtr;
byte[] encoded =new byte [MaxDataBytes];
int length = 0;
/* How this can be ported to delphi */
fixed (byte* benc = encoded)
{
encodedPtr = new IntPtr((void*)benc);
length = API.opus_encode(_encoder, inputPcmSamples, frames, encodedPtr, sampleLength);
}
encodedLength = length;
if (length < 0)
throw new Exception("Encoding failed - " + ((Errors)length).ToString());
return encoded;
}
The main code part that i'm looking for is :
fixed (byte* benc = encoded)
{
encodedPtr = new IntPtr((void*)benc);
/* API.opus_encode = is declared in an other Class */
length = API.opus_encode(_encoder, inputPcmSamples, frames, encodedPtr, sampleLength);
}
many thanks
You seem to want to know how to deal with the fixed block in the C#.
byte[] encoded =new byte [MaxDataBytes];
....
fixed (byte* benc = encoded)
{
encodedPtr = new IntPtr((void*)benc);
length = API.opus_encode(_encoder, inputPcmSamples, frames, encodedPtr, sampleLength);
}
This use of fixed is to pin the managed array to obtain a pointer to be passed to the unmanaged code.
In Delphi we just want an array of bytes, and a pointer to that array. That would look like this:
var
encoded: TBytes;
....
SetLength(encoded, MaxDataBytes);
....
length := opus_encode(..., Pointer(encoded), ...);
or perhaps:
length := opus_encode(..., PByte(encoded), ...);
or perhaps:
length := opus_encode(..., #encoded[0], ...);
depending on how you declared the imported function opus_encode and your preferences.
If MaxDataBytes was a small enough value for the buffer to live on the stack, and MaxDataBytes was known at compile time, then a fixed length array could be used.

C#. How fast insert Byte to Struct all time?

Code For NET 2.0.
I write function ByteArrayToObject for insert offset bytes in struct, but is it possible to quickly?
Is planned that there will be a lot of structures in which it is necessary to append the changed network information. If I can insert these bytes quickly to the right place, it will be organized in the protocol as one big structure.
Thank you for any help.
In my case, I do not like that every time to replace the bytes that have to do all the copy of the object func ObjectToByteArray.
/// <summary> Convert an object struct to a byte array </summary>
private static byte[] ObjectToByteArray(Object obj)
{
var size = Marshal.SizeOf(obj);
// Both managed and unmanaged buffers required.
var bytes = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
// Copy object byte-to-byte to unmanaged memory.
Marshal.StructureToPtr(obj, ptr, false);
// Copy data from unmanaged memory to managed buffer.
Marshal.Copy(ptr, bytes, 0, size);
// Release unmanaged memory.
Marshal.FreeHGlobal(ptr);
return bytes;
}
/// <summary> Need Faster ? </summary>
public static T ByteArrayToObject<T>(ref T obj, int StartOffset, params byte[] bytes)
{
int size = Marshal.SizeOf(obj);
int Length = (bytes.Length > size) ? size : bytes.Length;
byte[] Allbytes = ObjectToByteArray(obj);
Array.Copy(bytes, 0, Allbytes, StartOffset, Length - StartOffset);
var ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(Allbytes, 0, ptr, Length );
obj = (T)Marshal.PtrToStructure(ptr, typeof(T));
Marshal.FreeHGlobal(ptr);
return obj;
}
Example use
[Serializable]
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 1, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
struct Protocol
{
public byte f0;
public byte f1;
public short f2;
public byte f3;
public long f4;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 20000)]
public int[] Array; // 20000
}
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
for (byte i = 1; i < 10; i++)
{
sw.Reset();
sw.Start();
ob = ByteArrayToObject<Protocol>(ref ob,1, i, 0x11, i, 0x22, i);
sw.Stop();
Console.WriteLine("Tick =" + sw.ElapsedTicks);
}
Output
Tick =9940
Tick =686
Tick =593
Tick =474
Tick =562
Tick =5283
Tick =193
Tick =173
Tick =164
This is too long for a comment, but to expand on the unsafe approach:
unsafe struct Ex
{
public byte f0,f1,f2,f3,f4;
public fixed int buffer[20000];
}
class Program
{
public static unsafe void ByteArrayToEx(Ex* obj, int offset, params byte[] bytes)
{
// you should add some safely nets here sizeof(Ex) should used for size of struct
byte* p = (byte*)obj;
foreach (var b in bytes)
{
p[offset++] = b;
}
// dont return value, it is expensive!
}
unsafe static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
Console.WriteLine(Stopwatch.Frequency);
Ex e = new Ex { f0 = 0, f1 = 1, f2 = 2, f3 = 3, f4 = 4 };
ByteArrayToEx(&e, 2, 5, 6, 7);
for (int i = 0; i < 10; i++) {
sw.Restart();
ByteArrayToEx(&e, 2, (byte) i, 6, 7);
sw.Stop();
Console.WriteLine(sw.ElapsedTicks);
}
}
}
This may or may not work for you. Also dont return the value. You are already mutating the pointer to it. Returning a copy of such a big struct adds 10 ticks to every call to it.
Also, you need to do at least 1 warmup when bench marking. That is why the first number is so poor.
Results on my PC:
3312929
4
2
0
0
0
0
0
0
0
0
Rewrote a little
public static unsafe void ByteArrayToEx(ref Ex value, int offset, params byte[] bytes)
{
// you should add some safely nets here sizeof(Ex) should used for size of struct
fixed (Ex* obj = &value)
{
byte* p = (byte*)obj;
foreach (var b in bytes)
{
p[offset++] = b;
}
}
// dont return value, it is expensive!
}

Marshalling part of a struct

I've been trying to figure out whether it is possible to marshal a part of a struct into an array of bytes without any errors. The reason for this is because the part not going to be marshalled has a variable sized array. This is the the code I'm using.
C#:
public struct Random {
[MarshalAs(UnmanagedType.I4)]
public int a;
[MarshalAs(UnmanagedType.I4)]
public int b;
[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_RECORD)]
public Random1[] r;
}
public struct Random1 {
[MarshalAs(UnmanagedType.I4)]
public int c;
}
private void Form1_Load(object sender, EventArgs e) {
int size = Marshal.SizeOf(typeof(Random));
int s = 4;
Random r = new Random();
Random r1 = new Random();
r.a = 1;
r.b = 5;
r.r = new Random1[2];
r.r[0].c = 10;
r.r[1].c = 12;
IntPtr p = Marshal.AllocHGlobal(size);
try {
byte[] arr = new byte[size];
Marshal.StructureToPtr(r, p, false);
Marshal.Copy(p, arr, 0, 8);
Marshal.FreeHGlobal(p);
p = Marshal.AllocHGlobal(size);
Marshal.Copy(arr, 0, p, 8);
r1 = (Random) Marshal.PtrToStructure(p, typeof(Random));
Marshal.FreeHGlobal(p);
p = IntPtr.Zero;
Debug.WriteLine(r1.a);
Debug.WriteLine(r1.b);
Debug.WriteLine(r1.r[0].c);
Debug.WriteLine(r1.r[1].c);
} finally {
if (p != IntPtr.Zero) {
Marshal.FreeHGlobal(p);
}
}
}
When I try this code it gives me an ArgumentException in the StructureToPtr. What am I doing wrong or can this be done? If not I've read something about using IntPtr. Could someone tell me how to do this?
I've been thinking long and hard about this one, and after trying several (very hackish) options, I have arrived at the conclusion that what you are doing is not possible.
First of all, it isn't possible to directly marshal an array of variable length, because no meaningful size offset can be computed by the Marshal, and therefore the memory layout can not be determined.
If the struct wouldn't contain any non-blittable, non-primitive types, you could theoretically do something like this:
byte[] buffer = new byte[8];
Marshal.Copy(new IntPtr(&r), buffer, 0, 8);
IntegersOnlyStruct partialStruct;
fixed (byte* b = buffer)
partialStruct = *(IntegersOnlyStruct*) b;
And obtain the two integers contained in the struct that way. However, since your Random1 is a non-primitive, non-blittable type this approach won't get you very far either.
The IntPtr approach to keep a pointer to a memory location where your Random1 struct is kept in memory is an alternative that could possibly work, but I haven't gone in-depth on that, yet.
I think you may want to re-think the way you approach this, as it's not possible in its current form. If anybody can prove otherwise, I'd be happy to see how it can be done.

Convert a struct to bytes, save to file and read back to struct by another application in C#

I tried writing structures to a binary file but I can't read them correctly.
This is my struct. It has a dynamic number of "values". If the number of values is 3, then GetSize() will return 8 + (8*3) = 32
[StructLayout (LayoutKind.Sequential)]
public struct Sample
{
public long timestamp;
public double[] values;
public int GetSize()
{
return sizeof(long) + sizeof(double) * values.Length;
}
}
First, I convert the structure to bytes by:
public static byte[] SampleToBytes(Sample samp)
{
int size = samp.GetSize();
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(samp, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
Then, I write the bytes using BinaryWriter, and exit.
When I have to run the program again and read the file I saved. I use BinaryReader. I get every 32 bytes from the file and convert each array of 32 bytes back to struct using:
public static Sample BytesToSample(byte[] arr)
{
Sample samp = new Sample();
IntPtr ptr = Marshal.AllocHGlobal(32);
Marshal.Copy(arr, 0, ptr, 32);
samp = (Sample)Marshal.PtrToStructure(ptr, samp.GetType());
Marshal.FreeHGlobal(ptr);
return samp;
}
However, a SafeArrayTypeMismatchException occurs at PtrToStructure().
Could anyone please tell me what I am doing wrong?
Thanks.
You do realize that double[], being an array type, is a reference type? The struct holds the long followed by a reference to the heap object.
That would be the reason why it doesn't work, I think.
I believe you should simply write the elements of your array to a binary writer.

C# Copy variables into buffer without creating garbage?

Is it possible in C# .Net (3.5 and above) to copy a variable into a byte[] buffer without creating any garbage in the process?
For instance:
int variableToCopy = 9861;
byte[] buffer = new byte[1024];
byte[] bytes = BitConverter.GetBytes(variableToCopy);
Buffer.BlockCopy(bytes, 0, buffer, 0, 4);
float anotherVariableToCopy = 6743897.6377f;
bytes = BitConverter.GetBytes(anotherVariableToCopy);
Buffer.BlockCopy(bytes, 0, buffer, 4, sizeof(float));
...
creates the byte[] bytes intermediary object which becomes garbage (presuming a ref is no longer held to it)...
I wonder if using bitwise operators the variable can be copied directly into the buffer without creating the intermediary byte[]?
Use pointers is the best and the fastest way:
You can do this with any number of variables, there is no wasted memory, the fixed statement has a little overhead but it's too small
int v1 = 123;
float v2 = 253F;
byte[] buffer = new byte[1024];
fixed (byte* pbuffer = buffer)
{
//v1 is stored on the first 4 bytes of the buffer:
byte* scan = pbuffer;
*(int*)(scan) = v1;
scan += 4; //4 bytes per int
//v2 is stored on the second 4 bytes of the buffer:
*(float*)(scan) = v2;
scan += 4; //4 bytes per float
}
Why can't you just do:
byte[] buffer = BitConverter.GetBytes(variableToCopy);
Note that the array here is not an indirection into the storage for the original Int32, it is very much a copy.
You are perhaps worried that bytes in your example is equivalent to:
unsafe
{
byte* bytes = (byte*) &variableToCopy;
}
.. but I assure you that it is not; it is a byte by byte copy of the bytes in the source Int32.
EDIT:
Based on your edit, I think you want something like this (requires unsafe context):
public unsafe static void CopyBytes(int value, byte[] destination, int offset)
{
if (destination == null)
throw new ArgumentNullException("destination");
if (offset < 0 || (offset + sizeof(int) > destination.Length))
throw new ArgumentOutOfRangeException("offset");
fixed (byte* ptrToStart = destination)
{
*(int*)(ptrToStart + offset) = value;
}
}

Categories

Resources