Cross-platform C SDK logo

Cross-platform C SDK

Data binding

❮ Back
Next ❯
This page has been automatically translated using the Google Translate API services. We are working on improving texts. Thank you for your understanding and patience.

Data Binding is a technique that allows us to register the program structures or classes in order to automate certain tasks, such as synchronizing the data model with the user interface.


Functions

voiddbind (...)
voiddbind_enum (...)
type*dbind_create (...)
voiddbind_init (...)
voiddbind_remove (...)
voiddbind_destroy (...)
voiddbind_destopt (...)
type*dbind_read (...)
voiddbind_write (...)
voiddbind_default (...)
voiddbind_range (...)
voiddbind_precision (...)
voiddbind_increment (...)
voiddbind_suffix (...)

We understand by Data Binding the possibility of automatically synchronizing the structures of the program with different input/output sources. We start from the simple model (Listing 1) that we present in Arrays composed of a struct and an enum.

Listing 1: Simple data model based on struct.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
typedef struct _product_t Product;

typedef enum _type_t
{
    ekCPU,
    ekGPU,
    ekHDD,
    ekSCD
} type_t;

struct _product_t
{
    type_t type;
    String *code;
    String *description;
    Image *image64;
    real32_t price;
};

The first thing we have to do is register this model in dbind, a kind of general "database" within our application (Listing 2). It is only necessary to carry out this process once when starting the program. In this way, internal tables will be created with the description of each structure of the data model (Figure 1), leaving the program ready to automate certain tasks when working with objects of said classes.

  • Use dbind to register the fields of a structure.
  • Use dbind_enum to register the different values of enum types.
  • Listing 2: Registering the data model of (Listing 1).
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    dbind_enum(type_t, ekCPU, "");
    dbind_enum(type_t, ekGPU, "");
    dbind_enum(type_t, ekHDD, "");
    dbind_enum(type_t, ekSCD, "");
    dbind(Product, type_t, type);
    dbind(Product, String*, code);
    dbind(Product, String*, description);
    dbind(Product, Image*, image64);
    dbind(Product, real32_t, price);
    
    Scheme showing a data structure and its equivalent table.
    Figure 1: Internal tables created by dbind when registering the data model.

1. Synchronization with graphical interfaces

One of the most widespread uses of data binding is the possibility of synchronizing the graphical interface with the objects that make up the data model. This paradigm is known as MVVM (Model-View-ViewModel) (Figure 2)and we will delve deeper into it GUI Data binding.

Connections between a user interface and the data it manipulates.
Figure 2: Automatic synchronization of data and interface.

2. Read and write JSON

The parsing of JSON scripts can also be automated thanks to dbind (Figure 3). In JSON you will have detailed information on how to do it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
    "code":0,
    "size":80,
    "data":[
    {"id":0,
    "code":"i7-8700K",
    "description":"Intel BX80684I78700K 8th Gen Core i7-8700K Processor",
    type":0,
    "price":374.8899999999999863575794734060764312744140625,
    "image":"cpu_00.jpg",
    "image64":"\/9j\/4AAQSkZJRgABAQ....
    },
    ...
}
Connections between the fields of an object and a JSON script.
Figure 3: Data Binding in the analysis of JSON scripts.

3. Serialization with DBind

As we saw in Serialization and Unify serialization we need to define object reading and writing functions to send or receive them through streams. Fortunately, dbind knows the detailed composition of each registered object, so it's possible access the I/O without having to explicitly program these functions (Listing 3) (Figure 4).

Listing 3: Objects serialization with dbind.
1
2
3
ArrPt(Product) *products = dbind_read(stream, ArrPt(Product));
...
dbind_write(stream, products, ArrPt(Product));
Access to dbind tables to serialize objects.
Figure 4: Object reading/writing via dbind.

4. Default constructor

Thanks to dbind we can also create objects initialized with default values without creating specific constructors (Listing 4). They can also be destroyed guaranteeing the correct recursive release of the memory of all their fields.

The default values when initializing object fields are 0 for numbers, FALSE for booleans, "" for Strings and empty containers in the case of arrays or sets. If the object contains nested sub-objects, they will also be created/initialized recursively. These default values can be changed if necessary (Listing 5).


5. Numerical ranges

It is possible to configure the numeric fields uint32_t, int8_t, real64_t, etc to limit the accepted values (Listing 6). dbind will be responsible for validating the data every time it reads values from any data source (GUI, JSON, Streams, etc).


dbind ()

Adds a structure/class field to its internal table within dbind.

void
dbind(type,
      mtype,
      name);
type

Type of structure or class.

mtype

Type of field to register.

name

Name of the field within the structure.

Remarks

Errors will be generated at compile time if the indicated field does not belong to the structure. The method also works for classes in C++.


dbind_enum ()

Register an enum type value.

void
dbind_enum(type,
           value,
           const char_t *alias);
type

Enum type.

value

Value.

alias

Alias para el valor.

Remarks

dbind_enum(mode_t, ekIMAGE_ANALISYS, "Image Analisys"); it will use the string "Image Analisys" instead of "ekIMAGE_ANALISYS" for those I/O or interface operations that require displaying the literals of the enumeration. For example, to populate the fields of a PopUp linked with a data field.


dbind_create ()

Create an object of registered type, initializing its fields with the default values.

type*
dbind_create(type);
type

Object type.

Return

Newly created object or NULL if dbind does not recognize the data type.


dbind_init ()

Initializes the fields of an object of a registered type with the default values.

void
dbind_init(type *obj,
           type);
obj

Object whose memory has been reserved, but not initialized.

type

Object type.


dbind_remove ()

Destroys the memory reserved by the fields of an object of registered type, but does not destroy the object itself.

void
dbind_remove(type *obj,
             type);
obj

Object.

type

Object type.


dbind_destroy ()

Destroy an object of registered type. The memory allocated to the fields and sub-objects will also be released recursively.

void
dbind_destroy(type **obj,
              type);
obj

Object. Will be set to NULL after destruction.

type

Object type.


dbind_destopt ()

Destructor optional. Like dbind_destroy, but accepting NULL values for the object.

void
dbind_destopt(type **obj,
              type);
obj

Object to destroy.

type

Object type.


dbind_read ()

Creates an object of a registered type from the data read from a stream.

type*
dbind_read(Stream *stm,
           type);
stm

Reading stream.

type

Object type to read.

Return

Newly created object or NULL if there has been an error.


dbind_write ()

Write the content of an object of registered type in a write stream.

void
dbind_write(Stream *stm,
            const type *data,
            type);
stm

Writing stream.

data

Object to write.

type

Type of object to write.


dbind_default ()

Set the default value of a field.

void
dbind_default(type,
              mtype,
              name,
              mtype value);
type

Type of structure or class.

mtype

Field type.

name

Name of the field within the structure.

value

Default value as of now.


dbind_range ()

Set the maximum and minimum value in numeric fields.

void
dbind_range(type,
            mtype,
            name,
            mtype min,
            mtype max);
type

Type of structure or class.

mtype

Field type.

name

Name of the field within the structure.

min

Minimum value.

max

Maximum value.

Remarks

It will fail if used in non-numeric fields.


dbind_precision ()

Set the jump between two consecutive numerical values.

void
dbind_precision(type,
                mtype,
                name,
                mtype prec);
type

Type of structure or class.

mtype

Field type.

name

Name of the field within the structure.

prec

Accuracy (eg .05f in real32_t values).

Remarks

It will fail if used in non-numeric fields.


dbind_increment ()

Sets the increment of a numerical value when clicking on a UpDown control.

void
dbind_increment(type,
                mtype,
                name,
                mtype incr);
type

Type of structure or class.

mtype

Field type.

name

Name of the field within the structure.

incr

Increase.

Remarks

It will fail if used in non-numeric fields.


dbind_suffix ()

Set a suffix that will be added to the numerical value when converted to text.

void
dbind_suffix(type,
             mtype,
             name,
             const char_t *suffix);
type

Type of structure or class.

mtype

Field type.

name

Name of the field within the structure.

suffix

Suffix.

Remarks

It will fail if used in non-numeric fields.

❮ Back
Next ❯