Examples¶
Simple Example¶
Following C has a structure (person) with a set of elements that are written to a binary file.
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#pragma pack(1) // To secure no padding is added in struct
struct person
{
char name[50];
unsigned int age;
float height;
bool is_male;
unsigned int nbr_of_children;
unsigned int child_ages[10];
};
void main(void) {
struct person p;
memset(&p, 0, sizeof(struct person));
strcpy(p.name, "Foo Bar");
p.age = 42;
p.height = 1.75; // m
p.is_male = true;
p.nbr_of_children = 2;
p.child_ages[0] = 7;
p.child_ages[1] = 9;
FILE *f = fopen("simple_example.dat", "w");
fwrite(&p, sizeof(struct person), 1, f);
fclose(f);
}
To read the binary file using pycstruct following code required.
import pycstruct
person = pycstruct.StructDef()
person.add('utf-8', 'name', length=50)
person.add('uint32', 'age')
person.add('float32','height')
person.add('bool8', 'is_male')
person.add('uint32', 'nbr_of_children')
person.add('uint32', 'child_ages', length=10)
with open('simple_example.dat', 'rb') as f:
inbytes = f.read()
# Dictionary representation
result = person.deserialize(inbytes)
print('Dictionary object:')
print(str(result))
# Alternative, Instance representation
instance = person.instance(inbytes)
print('\nInstance object:')
print(f'name: {instance.name}')
print(f'nbr_of_children: {instance.nbr_of_children}')
print(f'child_ages[1]: {instance.child_ages[1]}')
The produced output will be:
Dictionary object:
{'name': 'Foo Bar', 'is_male': True, 'nbr_of_children': 2,
'age': 42, 'child_ages': [7, 9, 0, 0, 0, 0, 0, 0, 0, 0],
'height': 1.75}
Instance object:
name: Foo Bar
nbr_of_children: 2
child_ages[1]: 9
To write a binary file from python using the same structure using pycstruct following code is required.
import pycstruct
person = pycstruct.StructDef()
person.add('utf-8', 'name', length=50)
person.add('uint32', 'age')
person.add('float32','height')
person.add('bool8', 'is_male')
person.add('uint32', 'nbr_of_children')
person.add('uint32', 'child_ages', length=10)
# Dictionary representation
mrGreen = {}
mrGreen['name'] = "MR Green"
mrGreen['age'] = 50
mrGreen['height'] = 1.93
mrGreen['is_male'] = True
mrGreen['nbr_of_children'] = 3
mrGreen['child_ages'] = [13,24,12]
buffer = person.serialize(mrGreen)
# Alternative, Instance representation
mrGreen = person.instance()
mrGreen.name = "MR Green"
mrGreen.age = 50
mrGreen.height = 1.93
mrGreen.is_male = True
mrGreen.nbr_of_children = 3
mrGreen.child_ages[0] = 13
mrGreen.child_ages[1] = 24
mrGreen.child_ages[2] = 12
buffer = bytes(mrGreen)
# Write to file
f = open('simple_example_mr_green.dat','wb')
f.write(buffer)
f.close()
Embedded Struct Example¶
A struct can also include another struct.
Following C structure:
struct car_s
{
unsigned short year;
char model[50];
char registration_number[10];
};
struct garage_s
{
struct car_s cars[20];
unsigned char nbr_registered_parkings;
};
struct house_s {
unsigned char nbr_of_levels;
struct garage_s garage;
};
Is defined as following:
car = pycstruct.StructDef()
car.add('uint16', 'year')
car.add('utf-8', 'model', length=50)
car.add('utf-8', 'registration_number', length=10)
garage = pycstruct.StructDef()
garage.add(car, 'cars', length=20)
garage.add('uint8', 'nbr_registered_parkings')
house = pycstruct.StructDef()
house.add('uint8', 'nbr_of_levels')
house.add(garage, 'garage')
To print the model number of the first car:
# Dictionary representation
my_house = house.deserialize(databuffer)
print(my_house['garage']['cars'][0]['model'])
# Alternative, Instance representation
my_house = house.instance(databuffer)
print(my_house.garage.cars[0].model)
Parsing source code¶
Assume the C code listed in the first example is named simple_example.c. Then you could parse the source code instead of manually creating the definitions:
import pycstruct
definitions = pycstruct.parse_file('simple_example.c')
with open('simple_example.dat', 'rb') as f:
inbytes = f.read()
# Dictionary representation
result = definitions['person'].deserialize(inbytes)
print(str(result))
# Alternative, Instance representation
instance = definitions['person'].instance(inbytes)
The produced output will be the same is in the first example.
Parsing source code strings¶
You can also define the source in a string and parse it:
c_str = '''
struct a_struct {
int member_a;
int member_b;
};
struct a_bitfield {
unsigned int bmem_a : 3;
unsigned int bmem_b : 1;
};
'''
result = pycstruct.parse_str(c_str)
In the above example result[‘a_struct’] will be a pcstruct.StructDef instance and result[‘a_bitfield’] will be a pycstruct.BitfieldDef instance.