1

I need to store dense array data (3D arrays) from C code and then to read them into NumPy arrays (in another application). The data is around 100 kbytes of float values, C array as a pointer to the data. I am looking for a solution that does not require any external dependencies and can be implemented with the least effort.

What would be a good solution for that?

Thanks.

7
  • What you want in result? May be JSON would be best solution for you. Commented Nov 19, 2018 at 12:57
  • I would prefer binary format, since data amounts are very large. Also, no external dependencies in C. Commented Nov 19, 2018 at 12:59
  • 2
    The question is too broad because the properties of the input data (type of data, amount of data and is it constant/dynamic, etc.) are not specified. Question is also missing a metric by which solution can be considered "good solution". Commented Nov 19, 2018 at 13:10
  • The data is around 100 kbytes of float values, C array as a pointer to the data. I am looking for a solution that does not require any external dependencies and can be implemented with the least effort. So, simple and elegant. Commented Nov 19, 2018 at 13:52
  • 1
    If by 3D array you mean [][someNumber][someNumber] (i.e. a continuous block of data) instead of **[] (i.e. pointer to pointer to array), you can simply fwrite to a file then np.fromfile (with the correct dtype) + np.reshape Commented Nov 21, 2018 at 4:53

2 Answers 2

1

I've done some serialization for arm devices and network and I'would be happy to share my experience since you prefer binary serialization. I am using unions to serialize.Lets assume that you have a struct that holds some element, data and pointers and this holds data for a family member :

struct fam_member
{
    char name [ MAX_NAME_LEN + 1 ];
    int height;
    age_bracket_t age_bracket;
    fam_member_t* mother;
    fam_member_t* father;
}fam_member_t;

Age bracket is an enum:

typedef enum age_bracket
{
    under_18 = 0 , from_18_to_25 = 1 , from_26_to_40 = 2  , over_40 = 3
}age_bracket_t;

The main problem and the most common mistake is struct padding and not taking this to serious.Here is a good start if someone is not familiar with the issue. My simple solution is stream data down byte to byte (or bit to bit), do what you need to do with the serialized data (i.e. send them over a socket) and deserialize in the end. I define a Union like this:

typedef union serialized_struct
{
    fam_member_t family_member;
    unsigned char data[ (MAX_NAME_LEN + 1 ) + (sizeof(int)*3) ];

}serialized_struct_t;

(A few think about union here) The purpose of union is to save memory by using the same memory region for storing different objects at different times.In this example this will help us and actually serialize the family object struct for free.

Here is a function that serializes an array of family members (if you can do an area, single will be a piece of cake.That's why I choose an array here).

int serialize_array(fam_member_t* people , char* message , int elements)
{
    if((people == NULL ) || (message == NULL) || (elements < 1))
    {
        return -1;
    }
    int size = sizeof(fam_member_t);
    int i;
    for(i=0 ; i < elements ; i++)
    {
        serialized_struct_t x;
        memcpy((x.family_member.name) , people[i].name , MAX_NAME_LEN);
        x.family_member.age_bracket = people[i].age_bracket;
        x.family_member.height = people[i].age_bracket
        x.family_member.mother = people[i].mother;
        x.family_member.father = people[i].father;
        memcpy ( (message + (size * i)) , x.data , size );
    }
    return 0;
}

Here we initiate every data of every member inside the struct which lies in the union.Message holds serialized data.This is the deserialized function which will do the reverse

int desirialize_array(fam_member_t* people , char* message , int elements)
{
    if((people == NULL ) || (message == NULL) || (elements < 1))
    {
        return -1;
    }
    int size = sizeof(fam_member_t);
    serialized_struct_t y;
    int i;

    for (i =0 ; i < elements ; i ++ )
    {
        memcpy ( y.data , (message + (size * i)) , size );
        memcpy ( people[i].name , y.family_member.name , MAX_NAME_LEN);
        people[i].age_bracket = y.family_member.age_bracket;
        people[i].height = y.family_member.height;
        people[i].mother = y.family_member.mother;
        people[i].father = y.family_member.father;
    }
    return 0;
}

This is serialize and deserialize in c example.For your case where you need to deserialize this in python I think it will be easy if you figured out which will be the mean of serialization.JSON that @Alexander Tolkachev said for example could be a solution. I hope this simplified example helps you.

Sign up to request clarification or add additional context in comments.

Comments

1

This repository contains that you need!

https://github.com/souzomain/Packer

from Packer import Packer, Parser
packer = Packer()
packer.add_str("hello world")
print(f"packet size: {packer.get_size()} | packet: {packer.get_buffer()}")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.