Marshaling: C’s struct’s bit fields

english — Tags: , , — @ 23:02

If you are C programmer you might have noticed the existence of the bit fields in structs:

typedef struct {
int Some : 1;
int Bit : 2;
int Fields : 5;
} MyStruct;

Marshaling that code could be a pain in the ass. Before all, read Jonathan’s doc, then forget about the C’s sizeof, sum all the bit fields and get the value, in our sample struct we need to get that as 1 byte (1 + 2 + 5 = 8 bits = 1 byte) and then use the System.Collections.BitArray class, and convert that to their data type value. (I wrote a wrapper for doing this in a easiest way)

See the graphical explanation for understanding this.

See this sample

/* libsample.h */

typedef struct {
unsigned int Some : 1;
unsigned int Bit : 2;
unsigned int Fields : 5;
} MyStruct;

MyStruct get_mystruct (void);

int some (void);

/* libsample.c */
#include
#include "libsample.h"

MyStruct get_mystruct (void)
{
MyStruct a;
a.Some = 0x01; //One bit: 1 - 0
a.Bit = 0x02; //Two bits: 10 - 2
a.Fields = 0x1A; //Five bits: 0001 1010 - 26
//Full return: 1101 1010
return a;
}

int some (void)
{
return 0;
}

Then compiling


gcc -fPIC -Wall -g -c libsample.c
gcc -g -shared -Wl,-soname,libsample.so.0 \
-o libsample.so.0.0 libsample.o -lc
/sbin/ldconfig -n .
ln -sf libsample.so.0 libsample.so

Will create the shared libraries, let’s see the C# PInvoke.

using System;
using System.Collections;
using System.Runtime.InteropServices;

public class Sample
{
[StructLayout (LayoutKind.Sequential, Size=1, Pack=4)]
public struct MyStruct
{
public byte Value;

public uint GetSome ()
{
BitArray bArray = new BitArray (new byte[] { Value });
BitFieldFormater a = new BitFieldFormater (bArray);
return a.GetInt (0, 1);
}

public uint GetBit ()
{
BitArray bArray = new BitArray (new byte[] { Value });
BitFieldFormater a = new BitFieldFormater (bArray);
return a.GetInt (1, 2);
}

public uint GetFields ()
{
BitArray bArray = new BitArray (new byte[] { Value });
BitFieldFormater a = new BitFieldFormater (bArray);
return a.GetInt (3, 5);
}

public override string ToString ()
{
return "Some "+GetSome ()+" Bit "+GetBit ()+" Fields "+GetFields ();
}
}

[DllImport ("libsample.so")]
public static unsafe extern MyStruct get_mystruct (); //notice the return value

[DllImport ("libsample.so")]
public static unsafe extern int some (); //notice the return value

public static void Main ()
{
MyStruct myStruct = get_mystruct ();
System.Console.WriteLine ("some (): "+some ());
System.Console.WriteLine ("get_mystruct (): "+myStruct);
}
}

I’m using thre a class called BitFieldFormater for doing the magic:

using System;
using System.Collections;

public class BitFieldFormater
{
public BitFieldFormater (BitArray bitArray)
{
_bitArray = bitArray;
}

public uint GetUInt (int beginBit, int bitLength)
{
if ((beginBit + bitLength) > _bitArray.Count)
throw new ArgumentException ("Begin bit plus bit length is greater than array's length");

string requestedString = "";

//Getting bit values from the BitArray
for (int i = 0; i < bitLength; i++)
requestedString = Convert.ToInt32 (_bitArray [beginBit + i]) + requestedString;

return (uint) BinaryToInteger (requestedString);
}

private int BinaryToInteger (string binary)
{
char []elements = binary.ToCharArray ();
int result = 0, i = 0, pow = 0;
for (i = elements.Length - 1; i >= 0; i--) {
if (elements[i] == '1')
result += (int) Math.Pow (2, pow);
pow++;
}
return result;
}

private BitArray _bitArray;
}

Any bugs, please, let me know. I haven’t yet tested this class with structs with byte-size greater than 1… further testing is required.

UPDATED. Feb 3rd. Lot of useless code removed… what the fuck was I thinking!?

0 Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

  •  
    January 2006
    S M T W T F S
    « Dec   Feb »
    1234567
    891011121314
    15161718192021
    22232425262728
    293031  
  • Pages
  • Archives
  • Tag cloud
    2010 a11y accessibility books c# debian development english español february gnome hackweek january java june makeup march mono monohispano monohotdraw monouml nokia770 opensolaris opensuse personal pulque resolutions ruby ruby&c# tasque ubuntu uia uml vala yastroid
  • This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.
    (c) 2004-2010 Mario Carrion | powered by WordPress with Barecity