How to pass int[] from c# to c++ using shared memory - c#

I'm trying to pass an array of integers from c# to c++ via a managed memory file. Text was easy enough to get working, but I'm out of my depths in the c++ environment, and am not sure how to adjust this for an array of integers.
On the c# side, I pass:
pView = LS.Core.Platforms.Windows.Win32.MapViewOfFile(
hMapFile, // Handle of the map object
LS.Core.Platforms.Windows.Win32.FileMapAccess.FILE_MAP_ALL_ACCESS, // Read and write access
0, // High-order DWORD of file offset
ViewOffset, // Low-order DWORD of file offset
ViewSize // Byte# to map to the view
);
byte[] bMessage2 = Encoding.Unicode.GetBytes(Message2 + '\0');
Marshal.Copy(bMessage2, 0, pView2, bMessage2.Length);
Here pView2 is the pointer to the memory mapped file.
On the c++ side, I call:
LPCWSTR pBuf;
pBuf = (LPCWSTR) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
How would I change this to handle an array of integers instead? Thanks!

a) You can copy the int[] into a byte[]. You can use BitConverter.GetBytes for this or bit arithmetic (byte0 = (byte)(i >> 24); byte1 = (byte)(i >> 16); ...)
b) You can use unsafe code to bit-copy (blit) the int[] to the target byte[]
c) Maybe you can use Array.Copy. I think it can handle any blittable value type.
As per the comments I will elaborate on b):
int[] src = ...;
IntPtr target = ...;
var bytesToCopy = ...;
fixed(int* intPtr = src) {
var srcPtr = (byte*)intPtr;
var targetPtr = (byte*)target;
for(int i from 0 to bytesToCopy) {
targetPtr[i] = srcPtr[i];
}
}

Related

Does C# have a way to write an object with int fields (byte, ushort, ulong, etc.) as a byte array?

I'm trying to convert an object with only int fields (ushort, ulong, uint, int, etc.) into a byte array containing each int as a byte in the order that it appears in the object.
For example, if I have an object of the form
obj = {subobj: {uint firstProp: 500, ushort secondProp: 12}, byte lastProp: 5}
then I expect the byte array to be
{0, 0, 1, 244, 0, 12, 5}
I tried to create this byte array by using Serialization (as described in this answer), but I'm noticing there's a bunch of stuff before and after each byte. Based on this website, I believe this represents the database and the file, which I don't want.
I know that in C++ I can use reinterpret_cast<uint8_t*>(obj) to get the desired result. Is there an equivalent way to do this in C#?
You can try do something like this:
foreach(int value in obj)
{
byte lsbOfLsb = (byte)value;
byte msbOfLsb = (byte)(value >> 8);
byte lsbOfMsb = (byte)(value >> 16);
byte msbOfMsb = (byte)(value >> 24);
}
Obviously this is only the idea.
You should use a for loop instead of a foreach and Parse all elements to int e.g. .
Other way is to check the type of data with
typeof(value) //op 1
// OR
if(value is int) //e.g.
and then convert to byte as you need.

Byte[] to BitArray and back to Byte[]

As the title states, i'm trying to convert a byte array to bit array back to byte array again.
I am aware that Array.CopyTo() takes care of that but the byte array received is not the same as the original one due to how BitArray stores values in LSB.
How do you go about it in C#?
This should do it
static byte[] ConvertToByte(BitArray bits) {
// Make sure we have enough space allocated even when number of bits is not a multiple of 8
var bytes = new byte[(bits.Length - 1) / 8 + 1];
bits.CopyTo(bytes, 0);
return bytes;
}
You can verify it using a simple driver program like below
// test to make sure it works
static void Main(string[] args) {
var bytes = new byte[] { 10, 12, 200, 255, 0 };
var bits = new BitArray(bytes);
var newBytes = ConvertToByte(bits);
if (bytes.SequenceEqual(newBytes))
Console.WriteLine("Successfully converted byte[] to bits and then back to byte[]");
else
Console.WriteLine("Conversion Problem");
}
I know that the OP is aware of the Array.CopyTo solution (which is similar to what I have here), but I don't see why it's causing any Bit order issues. FYI, I am using .NET 4.5.2 to verify it. And hence I have provided the test case to confirm the results
To get a BitArray of byte[] you can simply use the constructor of BitArray:
BitArray bits = new BitArray(bytes);
To get the byte[] of the BitArray there are many possible solutions. I think a very elegant solution is to use the BitArray.CopyTo method. Just create a new array and copy the bits into:
byte[]resultBytes = new byte[(bits.Length - 1) / 8 + 1];
bits.CopyTo(resultBytes, 0);

What is the Fastest way to convert byte[] to float[] and vice versa?

Which is the fastest way to convert a byte[] to float[] and vice versa (without a loop of course).
I'm using BlockCopy now, but then I need the double memory. I would like some kind of cast.
I need to do this conversion just to send the data through a socket and reconstruct the array in the other end.
Surely msarchet's proposal makes copies too. You are talking about just changing the way .NET thinks about a memory area, if you dont' want to copy.
But, I don't think what you want is possible, as bytes and floats are represented totally different in memory. A byte uses exactly a byte in memory, but a float uses 4 bytes (32 bits).
If you don't have the memory requirements to store your data, just represent the data as the data type you will be using the most in memory, and convert the values you actually use, when you use them.
How do you want to convert a float (which can represent a value between ±1.5 × 10−45 and±3.4 × 10^38) into a byte (which can represent a value between 0 and 255) anyway?
(see more info her about:
byte: http://msdn.microsoft.com/en-us/library/5bdb6693(v=VS.100).aspx
float: http://msdn.microsoft.com/en-us/library/b1e65aza.aspx
More about floating types in .NET here: http://csharpindepth.com/Articles/General/FloatingPoint.aspx
You can use StructLayout to achieve this (from Stack Overflow question C# unsafe value type array to byte array conversions):
[StructLayout(LayoutKind.Explicit)]
struct UnionArray
{
[FieldOffset(0)]
public Byte[] Bytes;
[FieldOffset(0)]
public float[] Floats;
}
static void Main(string[] args)
{
// From bytes to floats - works
byte[] bytes = { 0, 1, 2, 4, 8, 16, 32, 64 };
UnionArray arry = new UnionArray { Bytes = bytes };
for (int i = 0; i < arry.Bytes.Length / 4; i++)
Console.WriteLine(arry.Floats[i]);
}
IEnumerable<float> ToFloats(byte[] bytes)
{
for(int i = 0; i < bytes.Length; i+=4)
yield return BitConverter.ToSingle(bytes, i);
}
Two ways if you have access to LINQ:
var floatarray = ByteArry.AsEnumerable.Cast<float>().ToArray();
or just using Array Functions
var floatarray = Array.ConvertAll(ByteArray, item => (float)item);

Convert into to byte array and insert into other array

I work in a c# wpf application in which I want to do several things. I'm working with byte arrays to compose MIDI Show Control messages (specified in the MSC Specification 1.0).
The structure of this message is that a 0x00 byte is like a comma between all the parts of the message. I compose a message like this:
byte[] data =
{(byte)0xF0, // SysEx
(byte)0x7F, // Realtime
(byte)0x7F, // Device id
(byte)0x02, // Constant
(byte)0x01, // Lighting format
(commandbyte), // GO
(qnumber), // qnumber
(byte)0x00, // comma
(qlist), // qlist
(byte)0x00, // comma
(byte)0xF7, // End of SysEx
};
I want the user to fill in unsigned integers (like 215.5) and I want to convert these numbers to bytes (without 0x00 bytes because then the message is interpreted wrong).
What is the best way to convert the numbers and place the byte array in the places mentioned above?
You might want to take a look at the BitConverter class, which is designed to convert base types into byte arrays.
http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx
But I'm not sure what guidance you are seeking for placing the items into your array. Array.Copy can work to simply copy the bytes in, but maybe I am misunderstanding.
Found it out like this:
Used someone else's converter code like this:
static byte[] VlqEncode(int value)
{
uint uvalue = (uint)value;
if (uvalue < 128)
return new byte[] { (byte)uvalue };
// simplest case
// calculate length of buffer required
int len = 0;
do
{
uvalue >>= 7;
} while (uvalue != 0);
// encode
uvalue = (uint)value;
byte[] buffer = new byte[len];
int offset = 0;
do { buffer[offset] = (byte)(uvalue & 127);
// only the last 7 bits
uvalue >>= 7; if(uvalue != 0) buffer[offset++] |= 128;
// continuation bit
} while (uvalue != 0);
return buffer;
}
Then I use this to convert the integer:
byte[] mybytearray = VlqEncode(integer);
I then make a new arraylist in which I add each item in sequence:
ArrayList mymessage = new ArrayList();
foreach(byte uvalue in mymessage)
{
mymessage.Add((byte)uvalue);
}
mymessage.Add((byte)0x00);
`
and so on until I have the correct message. I then only have to convert this a byte array like this:
byte[] data = new byte[mymessage.count];
data = (byte[])mymessage.ToArray(typeof(byte));`

C# little endian or big endian?

In the documentation of hardware that allows us to control it via UDP/IP,
I found the following fragment:
In this communication protocol, DWORD is a 4 bytes data, WORD is a 2 bytes data,
BYTE is a single byte data. The storage format is little endian, namely 4 bytes (32bits) data is stored as: d7-d0, d15-d8, d23-d16, d31-d24; double bytes (16bits) data is stored as: d7-d0 , d15-d8.
I am wondering how this translates to C#?
Do I have to convert stuff before sending it over?
For example, if I want to send over a 32 bit integer, or a 4 character string?
C# itself doesn't define the endianness. Whenever you convert to bytes, however, you're making a choice. The BitConverter class has an IsLittleEndian field to tell you how it will behave, but it doesn't give the choice. The same goes for BinaryReader/BinaryWriter.
My MiscUtil library has an EndianBitConverter class which allows you to define the endianness; there are similar equivalents for BinaryReader/Writer. No online usage guide I'm afraid, but they're trivial :)
(EndianBitConverter also has a piece of functionality which isn't present in the normal BitConverter, which is to do conversions in-place in a byte array.)
You can also use
IPAddress.NetworkToHostOrder(...)
For short, int or long.
Re little-endian, the short answer (to do I need to do anything) is "probably not, but it depends on your hardware". You can check with:
bool le = BitConverter.IsLittleEndian;
Depending on what this says, you might want to reverse portions of your buffers. Alternatively, Jon Skeet has specific-endian converters here (look for EndianBitConverter).
Note that itaniums (for example) are big-endian. Most Intels are little-endian.
Re the specific UDP/IP...?
You need to know about network byte order as well as CPU endian-ness.
Typically for TCP/UDP comms, you always convert data to network byte order using the htons function (and ntohs, and their related functions).
Normally network order is big-endian, but in this case (for some reason!) the comms is little endian, so those functions are not very useful. This is important as you cannot assume the UDP comms they have implemented follow any other standards, it also makes life difficult if you have a big-endian architecture as you just can't wrap everything with htons as you should :-(
However, if you're coming from an intel x86 architecture, then you're already little-endian, so just send the data without conversion.
I'm playing around with packed data in UDP Multicast and I needed something to reorder UInt16 octets since I noticed an error in packet header (Wireshark), so I made this:
private UInt16 swapOctetsUInt16(UInt16 toSwap)
{
Int32 tmp = 0;
tmp = toSwap >> 8;
tmp = tmp | ((toSwap & 0xff) << 8);
return (UInt16) tmp;
}
In case of UInt32,
private UInt32 swapOctetsUInt32(UInt32 toSwap)
{
UInt32 tmp = 0;
tmp = toSwap >> 24;
tmp = tmp | ((toSwap & 0xff0000) >> 8);
tmp = tmp | ((toSwap & 0xff00) << 8);
tmp = tmp | ((toSwap & 0xff) << 24);
return tmp;
}
This is just for testing
private void testSwap() {
UInt16 tmp1 = 0x0a0b;
UInt32 tmp2 = 0x0a0b0c0d;
SoapHexBinary shb1 = new SoapHexBinary(BitConverter.GetBytes(tmp1));
SoapHexBinary shb2 = new SoapHexBinary(BitConverter.GetBytes(swapOctetsUInt16(tmp1)));
Debug.WriteLine("{0}", shb1.ToString());
Debug.WriteLine("{0}", shb2.ToString());
SoapHexBinary shb3 = new SoapHexBinary(BitConverter.GetBytes(tmp2));
SoapHexBinary shb4 = new SoapHexBinary(BitConverter.GetBytes(swapOctetsUInt32(tmp2)));
Debug.WriteLine("{0}", shb3.ToString());
Debug.WriteLine("{0}", shb4.ToString());
}
from which output was this:
0B0A: {0}
0A0B: {0}
0D0C0B0A: {0}
0A0B0C0D: {0}
If you're parsing and performance is not critical, consider this very simple code:
private static byte[] NetworkToHostOrder (byte[] array, int offset, int length)
{
return array.Skip (offset).Take (length).Reverse ().ToArray ();
}
int foo = BitConverter.ToInt64 (NetworkToHostOrder (queue, 14, 8), 0);

Categories

Resources