How to write directly to memory in C# - c#

I am working on a serial port comms project. There is a piece of hardware sending signed 16 bit integer values, which are being received in to a C# PC application.
Each value is sent over two bytes, least significant byte first.
The performance of the is critical, so I'm looking at ways of reducing processing.
The C# Serial Port object provides a method ReadExisting, which returns the current buffered values as a string.
It also provides a method Read which can accept a byte array which is then populated with the bytes in the port buffer.
If I read all the values in to a byte array, I then have to join the two bytes together to get the 16 bit number.
I'm intrigued by the string returned from the ReadExisting method.
If I create an array of short (short[] MyValues), I could then get the memory location of the array, and simply write the string to that location. As long as I ensure the bytes are sent in the correct order, I could then simple read the 16 bit values when needed.
Alternatively, I could possibly create two arrays, one an array of shorts, the second an array of bytes twice the size of the first, both with the same memory location.
However, "here be dragons". I have no experience with C# and this level of memory access.
Some brief googleing suggests this is possible - this article has some interesting information:
https://www.developerfusion.com/article/84519/mastering-structs-in-c/
Before I head off down this particular rabbit hole, does anyone have any suggestions on how to achieve this level of memory manipulation?
Thanks

Try an overlay
static void Main(string[] args)
{
const int NUMBER_OF_BYTES = 100;
ByteInt16 byteInt = new ByteInt16();
byteInt.data = new byte[NUMBER_OF_BYTES];
byteInt.data2 = new UInt16[NUMBER_OF_BYTES / 2];
byteInt.data = Enumerable.Range(0, NUMBER_OF_BYTES).Select(x => (byte)x).ToArray();
UInt16[] results = byteInt.data2.Select(x => (UInt16)x).ToArray();
}
[StructLayout(LayoutKind.Explicit)]
public struct ByteInt16
{
[FieldOffset(0)]
public byte[] data;
[FieldOffset(0)]
public UInt16[] data2;
}

Related

How to detect a serial bit byte error in SerialPort class C#

I am using System.IO.Ports.SerialPort to read data from serial communication. The problem is that I want to determine which byte is bad when I read the byte array buffer and write a file. If I know which byte is bad, then I can recreate the correct file since I know the hash of the file. But It looks like System.IO.Ports.SerialPort only gives a way to "overwrite" an erroneous byte with the SerialPort.ParityReplace property. If I'm reading a million byte array, then I don't want to set a bit pattern as a replacement value and then search for this bit pattern in the massive array since I may have lots of matches. Is there a way for me to determine which byte failed a parity check when I read the byte buffer? If not, what would be a better way for me to get parity style error detection while sending a file over serial?
The code below is the way I'm currently looking at the serial data, but I'm open to other methods if its faster or gives more reliability.
//... earlier code:
_serialPort.ReadBufferSize = 100000000;
//... more irrelevant code
Thread.Sleep(150000); // wait for 150 seconds for the data to come in.
byte[] HundredKBBuffer = new byte[_serialPort.ReadBufferSize]; // the byte array I'll read from
//read data then discard buffer to get new data from the transmitting machine
_serialPort.Read(HundredKBBuffer, 0, HundredKBBuffer.Length);
_serialPort.DiscardInBuffer();
Console.WriteLine("data received");
//code that reads the byte array, looks for header and trailer and writes file
findHeadAndWriteDataToFile(HundredKBBuffer);
Have you tried reading the data in asynchronously as a stream instead of waiting to get the whole block at once? This sounds like it would allow you more opportunities to error check.
What is the correct way to read a serial port using .NET framework?
First idea is to you parity check after each byte, but you could loose speed communication (1 byte of data, 1 byte of parity check).
You can laso use CRC Code which is like an extension of the parity check. For example, you send 8 bytes and the ninth byte is the CRC. This allow you to control datas for a size-specified packet. The CRC function looks like this (it is the CRC-8 function, but you can use an other one):
private byte CRC8(byte[] Array, int length)
{
byte CRC = 0x00;
int length_buffer = length;
int length_refreshed = length;
CRC = Array[0];
length_refreshed--; ;
for (; length_refreshed > 0; length_refreshed--)
{
CRC = (byte)(((int)CRC) ^ (int)Array[length_buffer - length_refreshed]);
}
return CRC;
}
EDIT
Check here for CRC: https://en.wikipedia.org/wiki/Cyclic_redundancy_check

converting 8 bytes into one long

I am currently developing a C# 2D sandbox based game. The game world is filled with tiles/blocks. Since the world is so large the game can sometimes use more than what is allowed for 32-bit application.
My tiles consist of the following data inside a struct:
public byte type;
public byte typeWall;
public byte liquid;
public byte typeLiquid;
public byte frameX;
public byte frameY;
public byte frameWallX;
public byte frameWallY;
I am looking to encapsulate all this data within one "long" (64-bit integer).
I want properties to get and set each piece of data using bit shifting, etc... (I have never done this).
Would this save space? Would it increase processing speed? If so how can it be accomplished?
Thanks.
I am looking to encapsulate all this data within one "long" (64-bit integer).
You can use StructLayoutAttribute with LayoutKind.Explicit and then decorate fields with FieldOffsetAttribute specifying the exact position.
I want properties to get and set each piece of data using bit shifting, etc... (I have never done this).
Then use shift left (<<), shift right (>>) and masking (and && to extract / or || to write (don't forget about any non-zero bits in the target byte)) with 0xff to separate individual bytes. Read more about bitwise operations here.
Would this save space? Would it increase processing speed?
Did you measure it? Did you discover a performace / memory consuption problem? If yes, go optimize it. If not, do not do premature optimizations. In other words, don't blindly try without measuring first.
I don't know why you want to do this, but you can do it in this way:
byte type = 4;
byte typeWall = 45;
byte liquid = 45;
byte typeLiquid = 234;
byte frameX = 23;
byte frameY = 23;
byte frameWallX = 22;
byte frameWallY = 221;
byte[] bytes = new [] {type, typeWall, liquid, typeLiquid, frameX, frameY, frameWallX, frameWallY};
BitConverter.ToInt64(bytes, 0);
or using << (shift) operator.
As you can see by pasting the following code into linqpad :
void Main()
{
sizeof(byte).Dump("byte size");
sizeof(Int32).Dump("int 32");
sizeof(Int64).Dump("int 64");
sizeof(char).Dump("for good measure, a char:");
}
You'll get:
byte size 1
int 32 4
int 64 8
for good measure, a char: 2
So packing 8 bytes in an int64 will be the same, but you'll have to play with the bits yourself (if that's your thing, by all means, go for it :)

Copy a managed array to and from an unmanaged fixed size array

I'm doing an experiment as part of an R & D process. I need to be able to set values in a struct and retrieve and set them as a byte[].
Here's my struct:
[StructLayout(LayoutKind.Explicit, Size = 17)]
unsafe internal struct MyBuffer
{
[FieldOffset(0)]
internal fixed byte Bytes[17];
[FieldOffset(0)]
internal long L1;
[FieldOffset(8)]
internal long L2;
[FieldOffset(16)]
internal byte B;
}
Setting the values will obviously automatically set the byte[]:
MyBuffer test = new MyBuffer();
test.L1 = 100;
test.L2 = 200;
test.B = 150;
Inspecting test in debug mode yields what I expect.
What I need is as follows:
To be able to read the unmanaged fixed byte array as a 17 byte long managed array.
To be able to set the unmanaged fixed byte array from a 17 byte managed array.
NOTES:
If at all possible, I don't want to use marshalling as this is a time sensitive operation.
I can't omit the fixed directive as that throws a runtime error due to the overlapping of objects and non-objects in the struct.
You're already using unsafe code, so why not simply get a pointer to the structure and pass it? Doesn't this work?
MyBuffer bf = new MyBuffer();
bf.L1 = 23;
unsafe
{
MyBuffer* pStruct = &bf;
YourNativeMethod(pStruct);
}
[DllImport]
static extern void YourNativeMethod(MyBuffer* pStruct);
To avoid all marshalling, you might have to write a C++/CLI wrapper, I'm not sure if .NET does marshalling even if you pass an unsafe pointer.
You don't even need the byte-array, the native method certainly doesn't care whether you're passing a pointer to a byte array or a structure. Everything is a byte array :D
EDIT: Since your case doesn't explicitly call a native method, we have to go around this.
The problem is, fixed byte[] isn't actually a byte array at all. It's simply a sequence of 17 bytes, nothing more. That's not enough for a .NET array. So we have to copy it to a new array (it might be worthwhile to keep "buffer" byte arrays ready and recycle them to avoid allocations and deallocations). This can be done either through Marshal.Copy or some unsafe pointer fun:
byte[] bytes = new byte[17];
unsafe
{
IntPtr srcPtr = new IntPtr(bf.Bytes);
{
Marshal.Copy(srcPtr, bytes, 0, 17);
}
}
This uses direct memory copying, but does some checks. In my testing, it's a great way to copy bigger arrays (for me the break-even point was somewhere around 50 bytes). If your array is smaller, the overhead of those checks gets higher compared to total copy time, so you might want to use byte-by-byte copying instead:
byte[] bytes = new byte[17];
unsafe
{
byte* srcPtr = bf.Bytes;
fixed (byte* bPtr = bytes)
{
var j = 0;
while (j++ < 17)
{
*(bPtr + j) = *(srcPtr++);
}
}
}
I hope I don't have to tell you to be careful around this kind of code :)
In any case, I wouldn't worry about the performance too much and I'd use the Marshal.Copy variant, simply because your DB call is going to be the bottle-neck anyway. The safer option is better :)
There's also a few tricks you can use to speed this up, for example copying a whole int or long at a time, which the CPU is much better, although it's trickier. Trying with a simple variant (a length with a multiple of 4, copying a whole int at a time) cut my test runtime by four. If your data length is not a multiple of four, you'd simply copy the remainder as bytes.

Fast byte array masking in C#

I have a struct with some properties (like int A1, int A2,...). I store a list of struct as binary in a file.
Now, I'm reading the bytes from file using binary reader into Buffer and I want to apply a filter based on the struct's properties (like .A1 = 100 & .A2 = 12).
The performance is very important in my scenario, so I convert the filter criteria to byte array (Filter) and then I want to mask Buffer with Filter. If the result of masking is equal to Filter, the Buffer will be converted to the struct.
The question: What is the fastest way to mask and compare two byte arrays?
Update: The Buffer size is more than 256 bytes. I'm wondering if there is a better way rather than iterating in each byte of Buffer and Filter.
The way I would usually approach this is with unsafe code. You can use the fixed keyword to get a byte[] as a long*, which you can then iterate in 1/8th of the iterations - but using the same bit operations. You will typically have a few bytes left over (from it not being an exact multiple of 8 bytes) - just clean those up manually afterwards.
Try a simple loop with System.BitConverter.ToInt64(). Something Like this:
byte[] arr1;
byte[] arr2;
for (i = 0; i < arr1.Length; i += 8)
{
var P1 = System.BitConverter.ToInt64(arr1, i);
var P2 = System.BitConverter.ToInt64(arr2, i);
if((P1 & P2) != P1) //or whatever
//break the loop if you need to.
}
My assumption is that comparing/masking two Int64s will be much faster (especially on 64-bit machines) than masking one byte at a time.
Once you've got the two arrays - one from reading the file and one from the filter, all you then need is a fast comparison for the arrays. Check out the following postings which are using unsafe or PInvoke methods.
What is the fastest way to compare two byte arrays?
Comparing two byte arrays in .NET

Use the data in a c# byte array

I have an image, including image header, stored in a c# byte array (byte []).
The header is at the beginning of the byte array.
If I put the header in a struct (as I did in c++) it looks like this:
typedef struct RS_IMAGE_HEADER
{
long HeaderVersion;
long Width;
long Height;
long NumberOfBands;
long ColorDepth;
long ImageType;
long OriginalImageWidth;
long OriginalImageHeight;
long OffsetX;
long OffsetY;
long RESERVED[54];
long Comment[64];
} RS_IMAGE_HEADER;
How can I do it in c#, how can I get and use all the data in the image header (that stored in the beginning of the byte array)?
Thanks
Structs are perfectly fine in C#, so there should be no issue with the struct pretty much exactly as you've written it, though you might need to add permission modifiers such as public. To convert byte arrays to other primitives, there are a very helpful class of methods that include ToInt64() that will help you convert an array of bytes to another built in type (in this case long). To get the specific sequences of array bytes you'll need, check out this question on various techniques for doing array slices in C#.
The easiest way is to create an analog data structure in c#, I won't go into that here as it is almost the same. An example to read out individual the bytes from the array is below.
int headerVersionOffset = ... // defined in spec
byte[] headerVersionBuffer = new byte[sizeof(long)];
Buffer.BlockCopy(imageBytes, headerVersionOffset, headerVersionBuffer, 0, sizeof(long));
//Convert bytes to long, etc.
long headerVersion = BitConverter.ToInt64(headerVersionBuffer, 0);
You would want to adapt this to your data structure and usage, you could also accomplish this using a stream or other custom data structures to automatically handle the data for you.

Categories

Resources