Mashalling strange structs

  • Thread starter Thread starter wtfxxx
  • Start date Start date
W

wtfxxx

Hi,

How would I marshall this struct in C#? Thanks in advance:

typedef struct
{
ULONG bConnected :1;
ULONG bPnPEnabled :1;
ULONG bEnabled :1;
ULONG :1;
ULONG ConnectionState :6;
} PNP_STATUS;
 
How would I marshall this struct in C#? Thanks in advance:

typedef struct
{
ULONG bConnected :1;
ULONG bPnPEnabled :1;
ULONG bEnabled :1;
ULONG :1;
ULONG ConnectionState :6;
} PNP_STATUS;

Those are bitfields, for which C# has no native support. You can emulate
them with properties, though:

[StructLayout(LayoutKind.Sequential, Size = 4)]
struct PNP_STATUS {
private ushort s;

private bool getBit(int bit) {
return (s & (1 << bit)) != 0;
}

private void setBit(int bit, bool value) {
if (value) {
s |= (ushort) (1 << bit);
} else {
s &= (ushort) ~(1 << bit);
}
}

private int getIntSection(int startBit, int count) {
return (s >> startBit) & ((1 << count) - 1);
}

private void setIntSection(int startBit, int count, int value) {
s |= (ushort) ((value & (1 << count) - 1) << startBit);
}

public bool bConnected {
get { return getBit(0); }
set { setBit(0, value); }
}

public bool bPnPEnabled {
get { return getBit(1); }
set { setBit(1, value); }
}

public bool bEnabled {
get { return getBit(2); }
set { setBit(2, value); }
}

public int ConnectionState {
get { return getIntSection(4, 6); }
set { setIntSection(4, 6, value); }
}
}

The "Size = 4" above forces aligning to a 4-byte boundary, which is probably
what the unmanaged side expects/wants too. You may need to change this, however.
 
How would I marshall this struct in C#? Thanks in advance:
typedef struct
{
ULONG bConnected :1;
ULONG bPnPEnabled :1;
ULONG bEnabled :1;
ULONG :1;
ULONG ConnectionState :6;
} PNP_STATUS;

Those are bitfields, for which C# has no native support. You can emulate
them with properties, though:

[StructLayout(LayoutKind.Sequential, Size = 4)]
struct PNP_STATUS {
private ushort s;

private bool getBit(int bit) {
return (s & (1 << bit)) != 0;
}

private void setBit(int bit, bool value) {
if (value) {
s |= (ushort) (1 << bit);
} else {
s &= (ushort) ~(1 << bit);
}
}

private int getIntSection(int startBit, int count) {
return (s >> startBit) & ((1 << count) - 1);
}

private void setIntSection(int startBit, int count, int value) {
s |= (ushort) ((value & (1 << count) - 1) << startBit);
}

public bool bConnected {
get { return getBit(0); }
set { setBit(0, value); }
}

public bool bPnPEnabled {
get { return getBit(1); }
set { setBit(1, value); }
}

public bool bEnabled {
get { return getBit(2); }
set { setBit(2, value); }
}

public int ConnectionState {
get { return getIntSection(4, 6); }
set { setIntSection(4, 6, value); }
}
}

The "Size = 4" above forces aligning to a 4-byte boundary, which is probably
what the unmanaged side expects/wants too. You may need to change this, however.

Thanks J, I didnt know what that struct was called or doing. This
cleared up a lot of questions.
 
Hi,

How would I marshall this struct in C#? Thanks in advance:

typedef struct
{
ULONG bConnected :1;
ULONG bPnPEnabled :1;
ULONG bEnabled :1;
ULONG :1;
ULONG ConnectionState :6;

} PNP_STATUS;

You might also want to have a look at BitVector32 struct. It
encapsulates a 32-bit int (as the name implies), and allows you to
"slice" it into chunks of several bits using the CreateSection method,
and then access them individually. For your case, it would be
something like this:

struct PNP_STATUS
{
public static readonly BitVector32.Section
bConnected = BitVector32.CreateSection(1), // 1 bit at the
beginning
bPnPEnabled = BitVector32.CreateSection(1, bConnected), // 1 bit
following bConnected
bEnabled = BitVector32.CreateSection(1, bPnPEnabled), // 1 bit
following bPnPEnabled
padding = BitVector32.CreateSection(1, bEnabled ), // 1 bit
following bEnabled
ConnectionState = BitVector32.CreateSection(1, padding); // 6 bits
following padding

public BitVector32 Data;
}

Then you can access it like this:

PNP_STATUS status;
if (status[PNP_STATUS.bConnected] == 1)
{
status[PNP_STATUS.ConnectionState]++;
}

When you have do deal with a large number of bitfields, this makes it
a little bit more obvious. Of course, it is still better to hide all
those Section objects inside the struct as private fields, and expose
them via properties.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top