How to set an int to byte* C# - c#

How can I convert an int to a byte* at a certain index in a byte*?
Ideally I would like to have something like:
unsafe{
byte* igm=stackalloc byte[8];
igm[4]=4283;
}
It would set the first part of the bit to igm[4] and the rest into igm[5].
Edit: I realize there may be a lot of possible ways to handle this, i am looking for the most efficient way if possible.

try this:
unsafe
{
byte* igm = stackalloc byte[8];
*(int*)(igm + 4) = 4283;
}
Once you realize that you can use simple pointer arithmetic to index anywhere in your byte array, things get a LOT easier.

The type system in C# will prevent you from doing that, as you might have noticed. However, you can cast your pointers to be the appropiate types:
unsafe
{
byte* igm = stackalloc byte[8];
int* intPtr = (int*)igm;
intPtr[1] = 4283;
}

You need to break your int to sizeof(int) count of bytes and then manually set this parts to your byte* at specified indexes.
This will be safer as you'll know WHAT and WHERE you place your data.

Related

Byte-array to float using bitwise shifting instead of BitConverter

I'm receiving byte-arrays containing float variables (32 bit).
In my C# application I'd like to turn byte[] byteArray into a float using bitwise shifting (because it's a lot faster than BitConverter).
Turning a byte-array into a short works like this:
short shortVal = (short)((short)inputBuffer [i++] << 8 | inputBuffer [i++]);
How do I do this for float-variables?
Let's gut the BCL and use its intestines for our purposes:
unsafe public static float ToSingle (byte[] value, int startIndex)
{
int val = ToInt32(value, startIndex);
return *(float*)&val;
}
You can implement ToInt32 using bit shifting.
If you don't need endianness behavior a single unsafe access can give you the float (assuming it's aligned).
Alternatively, you can use a union struct to convert an int to a float.
To get away from C# conventional methods and obtain fast performance, you'll most likely have to implement "unsafe" behavior. You could do something like the C style memory copy.
unsafe public static void MemoryCopy (void* memFrom, void* memTo, int size) {
byte* pFrom = (byte*)memFrom;
byte* pTo = (byte*)memTo;
while (size-- >= 0)
*pTo++ = *pFrom++;
}
This assumes that the float's endianness is the same going into the byte[] as it on the other end.
To use this you'll have to first fix the byte array since the runtime can move it anytime it wants during garbage collection. Something like this:
float f;
unsafe {
fixed (byte* ptr = byteArray) {
MemoryCopy (ptr, &f, sizeof(float));
}
}

int* pointer not compiling while ushort* and byte* are fine

I do have the follwing struct in a C# wrapper for some unmanaged code. I try to hand over some data using pointers, which is fine for the ushort* and byte* part, but does not work for the fixed int.
[StructLayout(LayoutKind.Sequential)]
unsafe public struct IMAGE
{
public fixed int nSize[2];
public ushort* pDepthIm;
public byte* pColorIm;
}
To fill this struct with some information, I use:
unsafe public void LoadImage(ushort[] depthImage, byte[] rgbImage, int[] size)
{
unsafe
{
fixed (int* pSize = size)
fixed (ushort* pDepth = depthImage)
fixed (byte* pRGB = rgbImage)
{
_im.nSize = pSize;
_im.pColorIm = pRGB;
_im.pDepthIm = pDepth;
...
}
}
}
At _im.nSize = pSize; the compiler shows an error, stating:
You cannot use fixed size buffers contained in unfixed expressions.
Try using the fixed statement.
I already noticed that the int is initialized in a different way (not with the Pointer-*, but as fixed int), but I can't figure out how to hand over the value. When hovering over the variable, it is shown as int*...
Update: I came across the MSDN error reference for the mentioned message. I'm now sure it has to do with the fixed statement in the IMAGE struct, but I still have no idea how to fix it.
You can't assign a pointer to an array. You have to use memcpy.
memcpy(_im.nSize, size, sizeof(_im.nSize));
As a matter of fact you can't assign anything to an array. You can modify array's value, but not reassign it.
I would also check for the array length, pass it as a parameter or check it's .length if the languge allows it.
If found a way to access the fixed int[2] like this:
public unsafe void LoadImage(ushort[] depthImage, byte[] rgbImage, int[] size)
{
unsafe
{
fixed (int* pSize = _im.nSize)
fixed (ushort* pDepth = depthImage)
fixed (byte* pRGB = rgbImage)
fixed (S_IMAGE* pim = &_im)
{
pSize[0] = size[0];
pSize[1] = size[1];
_im.pColorIm = pRGB;
_im.pDepthIm = pDepth;
}
}
}
Im not sure if this is a good way or if this is how it is meant to be, but at least it works as expected...

Casting int on a c++ logic layer

I am new to c++ and as for now I have quite a heavy task on my work, I have a gui made in wpf and I need to send parameters from the gui to the c++ the (which as for now I already handled)
My problem is that on the c++ layer I get the info as a BYTE* I need to reinterprete the values to their "original" state (the first translation from ont\float to byte array is being made on the C# level using the static BitConvertor class) as for now I used this little method -
void GetNextValue(byte* bytes, deque<BYTE> *buffer)
{
bytes[3] = buffer->front();
buffer->pop_front();
bytes[2] = buffer->front();
buffer->pop_front();
bytes[1] = buffer->front();
buffer->pop_front();
bytes[0] = buffer->front();
buffer->pop_front();
}
But for an integer value of 1 I get a really high number, on the other hand going directly for the int value in the whole buffer will yield the correct answer...(i.e. int x = pBuffer[4]), any help or suggestions will be gladly accepted..
BTW-
I used
_rxBuffer.insert( _rxBuffer.end(), pBuffer, pBuffer + nLength);
To convert the BYTE* of data to -
deque<BYTE> _rxBuffer;
If you have an array of byte[4] you can just convert it to integer by this:
byte bytes[4];
int value = *(int*)bytes;
But beware, depending on endianess of your platform you may or may need not swap bytes order (try to replace 3<>0 and 2<>1 in bytes).

C# - Convert unsafe byte* to byte[]

I have an unsafe byte* pointing to a native byte array of known length. How can I convert it to byte[]?
An unsafe sbyte* pointing to a zero-terminated native string can be converted to a C# string easily, because there is a conversion constructor for this purpose, but I can't find a simple way to convert byte* to byte[].
If ptr is your unsafe pointer, and the array has length len, you can use Marshal.Copy like this:
byte[] arr = new byte[len];
Marshal.Copy((IntPtr)ptr, arr, 0, len);
But I do wonder how you came by an unsafe pointer to native memory. Do you really need unsafe here, or can you solve the problem by using IntPtr instead of an unsafe pointer? And if so then there's probably no need for unsafe code at all.
The Marshal class could help you.
byte[] bytes = new byte[length];
for(int i = 0; i < length; ++i)
bytes[i] = Marshal.ReadByte(yourPtr, i);
I think you might use Marshal.Copy too.

Convert piece of code from c++ to c#

i'm trying to convert code from c++ to c#.. but i'm stuck.
Can somebody let me know where i'm wrong?
C++ code is:
void CALLBACK Test(void *buffer, DWORD length)
{
BYTE *b=(BYTE*)buffer, temp[20000];
DWORD p=0;
while (p<length)
{
DWORD c=min(length-p, sizeof(temp));
memcpy(temp, b+p, c);
c=SendData(dummy, temp, c);
if (c==-1) break;
p+=c;
}
}
where is SendData(int, byte[], int)
And current c# code
void Test(IntPtr buffer, int length)
{
byte[] temp = new byte[20000];
byte[] b = new byte[length];
Marshal.Copy(buffer, b, 0, length);
long p=0;
while (p<length)
{
long c=Math.Min(length-p, 20000);
Array.Copy(temp, b+p, c);
c=SendData(dummy, temp, (int)c);
if (c==-1) break;
p+=c;
}
}
I'm not sure did I did it correctly, but I can see I cannot apply operator + to b+s because it's long and byte[].
Thanks
I think you want to use the 5-arg version of Array.Copy, which lets you pass offsets into both the start and destination arrays. This is the more "C#" way of doing things as opposed to pointer arithmetic.
In C++ you may add a DWORD (an int, really) to a pointer and the compiler knows to offset the address of the pointer by the specified amount. C# doesn't let you do that, normally. (There is a way to do pointer arithmetic in C#, but don't.) So, in the C# version, you need another way to copy at offset p relative to the start of b. One of the overloads of Array.Copy will let you do that. Something like:
Array.Copy(temp, 0, b, p, c);
You may want to look at: How to split a byte array, because that is in effect what you are trying to accomplish with the b+pportion.

Categories