BlndLeadingDef
BlndLeadingDef

Reputation: 37

C++ Conversion To C#

I've got the following situation:

struct object1  {

    bool a:1;
    bool b:1;
    uint8_t c:2;
    bool d:1;
    abc  e:3;

    uint16_t header;
    uint8_t footer;
    uint8_t mid[4];
}

I may not know the syntax but in C# playing with bits isn't as easy as C++. I've used the BitArray and BitConverter Classes to make methods to populate the data but I've run into the problem:

object1 * rqr = (object1  *) &Msg.Data[2];

Basically they are casting the object to an array of bytes. Every search I've done screams serialization but to truly convert the above line I can't have any extra metadata or anything.

I really do want to create a pointer to a memory location and "cast" that location to said object. Is this possible? If not, is there a solution to this issue? I can't imagine that bit manipulation on this level has been left out completely. I'd default to me just not knowing before assuming that.

Edit:: I understand that C# does not allow for pointers onto manage types. What I'm asking is if there was a way to say:

Byte[] ayData = new Byte[8];
ObjectOfSize8 nObject =  (ObjectOfSize8)ayData;

I understand the above will not work, but, is there something in the language that will allow data casting if you're smart enough to understand the memory sizes of the objects?

Upvotes: 1

Views: 231

Answers (2)

Jim Mischel
Jim Mischel

Reputation: 134045

You can solve your bitfield problem with a struct that handles the bit shifting and masking for you:

[StructLayout(LayoutKind.Sequential, Size=1)]
public struct BitField8
{
    private byte _bits;

    private static readonly byte[] Masks = new byte[] { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
    public BitField8(int val)
    {
        _bits = (byte) val;
    }

    public byte Get(int bit, int length = 1)
    {
        int shift = bit + length - 1;
        return (byte) ((_bits >> shift) & Masks[length-1]);
    }

    public void Set(int bit, int length, int val)
    {
        int mask = Masks[length-1];
        int shift = bit + length - 1;
        val = (val & mask) << shift;
        mask = ~(mask << shift);
        _bits = (byte)((_bits & mask) | val);
    }
}

So in your example:

bool a:1;
bool b:1;
uint8_t c:2;
bool d:1;
abc  e:3;

You would set a by calling Set(0, 1, 1) (set a to 1).

To give c the value of 3, you would call Set(3, 2, 3). (c occupies bits 2 and 3).

That basically duplicates the functionality of C++ bitfields, although I'll admit that I might have the bit order wrong. I don't really know if the C++ compiler put a at bit 0 or at bit 7.

You can do something similar with 16-bit, 32-bit, and 64-bit bitfields.

So your struct would contain:

BitField8 myBitfield;

Upvotes: 2

David Heffernan
David Heffernan

Reputation: 613322

You cannot do what you ask with type casting in C#. I suspect the cleanest way to do what you need may be to pin the C# struct. Then you've got an IntPtr that you can use with Marshal.Copy to copy to and from a byte array.

As for the bitfields, they'll need to be managed using bitwise shift, bitwise OR and bitwise AND operations.

Upvotes: 1

Related Questions