SDK Multiplataforma en C logo

SDK Multiplataforma en C

Data binding

❮ Anterior
Siguiente ❯

Funciones

dbindst_tdbind (...)
dbindst_tdbind_enum (...)
dbindst_tdbind_binary (...)
dbindst_tdbind_alias (...)
dbindst_tdbind_unreg (...)
type*dbind_create (...)
type*dbind_copy (...)
voiddbind_init (...)
voiddbind_remove (...)
voiddbind_destroy (...)
voiddbind_destopt (...)
intdbind_cmp (...)
bool_tdbind_equ (...)
type*dbind_read (...)
voiddbind_write (...)
voiddbind_default (...)
voiddbind_range (...)
voiddbind_precision (...)
voiddbind_increment (...)
voiddbind_suffix (...)

En lenguajes de alto nivel, como .NET o Javascript, data binding (o vinculación de datos) es una técnica que permite establecer una conexión automática entre los datos de una aplicación y sus elementos de interfaz de usuario. El módulo DBind de NAppGUI implementa y extiende este concepto en lenguaje C, ya que posibilita la automatización de ciertas tareas sobre las estructuras y objetos de nuestra aplicación (Figura 1). Gracias a ello evitaremos generar código redundante y problemático de mantener, proporcionando una interfaz general para:

  • Creación, destrucción y copia de objetos.
  • Comparación de objetos.
  • Serialización: Lectura y escritura en streams.
  • Importación/exportación en diferentes formatos, como JSON.
  • Vinculación con interfaces de usuario.
  • Esquema que muestra una estructura de datos, su tabla en DBind y las operaciones que se pueden realizar de forma automática.
    Figura 1: Automatización de operaciones sobre datos con DBind.

1. Registrar tipos de datos

  • Utiliza dbind para registrar estructuras.
  • Utiliza dbind_enum para registrar enumerados.

El primer paso para utilizar data binding es registrar en DBind los tipos definidos por el usuario (struct y enum). Los tipos básicos con conocidos de antemano, ya que se añaden automáticamente al iniciar el programa. Partimos de nuestro sencillo modelo de datos (Listado 1):

Listado 1: Modelo de datos basado en la estructura Product.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
typedef enum _type_t
{
    ekCPU,
    ekGPU,
    ekHDD,
    ekSCD
} type_t;

typedef struct _product_t
{
    type_t type;
    String *code;
    String *desc;
    Image *image;
    real32_t price;
} Product;

Lo añadiremos a DBind al iniciar la aplicación (Listado 2). Esto creará una suerte de "base de datos" que albergará el nombre, tipo y desplazamiento de los campos de cada estructura (Figura 2). Gracias a esta información será posible manipular objetos de forma totalmente automática y sin la necesidad de crear código adicional por parte del programador.

Listado 2: Registrando el modelo de datos de (Listado 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*, desc);
dbind(Product, Image*, image);
dbind(Product, real32_t, price);
Esquema que muestra una estructura de datos y su tabla equivalente.
Figura 2: Tablas internas creadas por DBind al registrar el modelo de datos.

1.1. Alias de tipos

dbind() utiliza el nombre del tipo de cada campo de la estructura para localizarlo dentro de su registro interno. Utilizar tipos no registrados conllevará un error de tipo ekDBIND_TYPE_UNKNOWN. Por ejemplo, en (Listado 3), DBind no conoce que el tipo color_t es, en realidad, un uint32_t:

Listado 3: Uso indebido de tipos no registrados.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
typedef uint32_t color_t;
typedef struct _product_t
{
    type_t type;
    String *code;
    String *desc;
    Image *image;
    real32_t price;

    color_t color;
} Product;

// ekDBIND_TYPE_UNKNOWN
dbind(Product, color_t, color);

Para soportar tipos equivalentes declarados mediante el typedef de C, tan solo deberemos añadirlos como 'alias' en DBind (Listado 4):

Listado 4: Declaración de un typedef mediante alias en DBind.
1
2
3
4
5
6
typedef uint32_t color_t;
...
dbind_alias(uint32_t, color_t);
...
// ekDBIND_OK 'color_t' is a known type
dbind(Product, color_t, color);

2. Creación de objetos

Una de las primeras utilidades de DBind es la creación, inicialización, copia y destrucción de objetos sin tener que programar explícitamente constructores y destructores. Esta operativa puede llegar a ser engorrosa cuando existen objetos anidados o contenedores como parte del objeto principal. En (Listado 5) tenemos un sencillo ejemplo de construcción y destrucción de un objeto de tipo Product sin haber definido explícitamente funciones para ello. Al estar registrado, DBind sabe como reservar memoria e inicializar cada campo de acuerdo a unos Valores por defecto.

Listado 5: Construcción y destrucción automática.
1
2
3
4
5
Product *prod = dbind_create(Product);
// 'prod' correctly initialized by default
...
dbind_destroy(&prod, Product);
// 'prod' correctly destroyed including all its fields

2.1. Inicialización de objetos

dbind_create() y dbind_destroy() actúan sobre el Segmento Heap, es decir, reservan y liberan la memoria dinámica necesaria por el propio objeto. Pero en ocasiones es posible que los objetos residan en un espacio de memoria gestionada automáticamente, bien porque se alojen en el Segmento Stack o bien en un contenedor tipo ArrSt o SetSt. En estos casos utilizaremos los inicializadores y liberadores que trabajarán sobre los campos internos del objeto sin preocuparse por la memoria del propio objeto (Listado 6). Evidentemente, los campos internos de una estructura inicializada con dbind_init() pueden reservar memoria dinámica que será liberada por dbind_remove().

Listado 6: Inicialización y liberación automática.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// Object in stack
Product prod1;
// Object in container
Product *prod2 = arrst_new(arrst, Product);

dbind_init(&prod1, Product);
dbind_init(prod2, Product);
// 'prod1', 'prod2' correctly initialized by default
...
dbind_remove(&prod1, Product);
dbind_remove(prod2, Product);
// ONLY 'prod1', 'prod2' fields destroyed
// The object itself memory will be managed automatically
// Because lives in stack or container

2.2. Copia de objetos

La duplicación de objetos también está automatizada, permitiendo una copia "profunda" y recursiva de todos los campos y objetos anidados, sin necesidad de definir ninguna función de copia (Listado 7).

Listado 7: Copia de objetos automática.
1
2
3
Product *nprod = dbind_copy(prod, Product);
...
dbind_destroy(&nprod, Product);

2.3. Edición de objetos

Una vez creado un objeto de un tipo registrado, este podrá ser editado y manipulado como cualquier objeto de C ya que, en realidad, no deja de ser una instancia de un tipo struct (Listado 8).

Listado 8: Editando objetos gestionados con DBind.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Product *prod1 = dbind_create(Product);
Product prod2;
dbind_init(&prod2, Product);
// 'prod1', 'prod2' are really struct instances
...
str_upd(&pr1->desc, "Another desc");
...
pr2.price = 100.23f;
...
bstd_printf("Product name: %s with price: %.2f\n", tc(pr2.desc), pr2.price);
...
dbind_destroy(&prod1, Product);
dbind_remove(&prod2, Product);

2.4. Tipos básicos

Como ya comentamos al principio, únicamente tenemos que registrar las estructuras y enumerados propios de nuestra aplicación. DBind ya conoce de antemano los tipos básicos y las cadenas de caracteres (String), por lo que serán aceptados como tipos de campo en struct:

  • Booleano: bool_t.
  • Enteros: uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t.
  • Reales: real32_t, real64_t.
  • Cadenas de texto dinámicas: String.
El uso de tipos no registrados será ignorado por dbind(). Utiliza dbind_alias() si quieres utilizar tipos básicos equivalentes.

2.5. Objetos anidados

Un objeto registrado puede formar parte de otro objeto registrado, utilizando reserva de memoria estática o dinámica (Listado 9). En este caso, los objetos anidados stock1 y stock2 de tipo Stock serán inicializados con sus valores por defecto al crear el objeto principal mediante dbind_create(Product).

Listado 9: Objetos tipo Stock anidados en Product.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
typedef struct _stock_t
{
    uint32_t min_units;
    uint32_t max_units;
    uint32_t cur_units;
    String *location;
    bool_t required;
} Stock;

typedef struct _product_t
{
    ...
    Stock stock1;   // Static alloc
    Stock *stock2;  // Dynamic alloc
} Product;

// Stock struct to DBind
dbind(Stock, uint32_t, min_units);
dbind(Stock, uint32_t, max_units);
dbind(Stock, uint32_t, cur_units);
dbind(Stock, String*, location);
dbind(Stock, bool_t, required);

// Stock fields in Product
dbind(Product, Stock, stock1);
dbind(Product, Stock*, stock2);
...

Product *prod = dbind_create(Product);
// 'stock1', 'stock2' instances correctly initialized
bstd_printf("Product locations: %s, %s\n", tc(prod->stock1.location), tc(prod->stock2->location));
dbind_destroy(&prod, Product);

2.6. Objetos binarios

Un objeto binario (u opaco) es aquel cuya declaración está oculta, es decir, no tenemos acceso a (o no queremos registrar en DBind) su tipo struct. Este tipo de objetos serán manejados como bloques de bytes indivisibles, sin entrar en detalles sobre la naturaleza o origen de su contenido. Un ejemplo claro lo tenemos con el tipo Image, declarado automáticamente por NAppGUI. Gracias a ello podremos utilizar imágenes dentro de nuestro modelo de datos:

Listado 10: Uso de imágenes (objeto binario) con DBind.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
typedef struct _product_t
{
    ...
    Image *image;
} Product;

dbind(Product, Image*, image);

Product *prod = dbind_create(Product);
if (prod->image != NULL)
{
    // Exists a default image
    draw_image(prod->image);
}

// product->image will be destroyed if exists.
dbind_destroy(&prod, Product);

Si queramos registrar nuestros propios tipos binarios, deberemos proveer a DBind de funciones para copiar, serializar y destruir objetos de dicho tipo (Listado 11):

Listado 11: Registro de nuestro tipo binario.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
typedef _mytype_t MyType;   // Definition is hidden

static MyType *mytype_copy(const MyType *obj)
{
    // Return a copy of 'obj'
}

static MyType *mytype_read(Stream *stm)
{
    // Read the object from stream data and return it
}

static void mytype_write(Stream *stm, const MyType *obj)
{
    // Write the object data into the stream
}

static void mytype_destroy(MyType **obj)
{
    // Destroy the object here
}

// Register 'MyType' objects in DBind
dbind_binary(MyType, mytype_copy, mytype_read, mytype_write, mytype_destroy);

// Now we can use 'MyType' objects with DBind
typedef struct _product_t
{
    ...
    MyType *mytype;
} Product;

dbind(Product, MyType*, mytype);

Product *prod = dbind_create(Product);
if (prod->mytype != NULL)
{
    // Exists a default 'MyType' object
}

// 'prod->mytype' will be destroyed if non-NULL.
dbind_destroy(&prod, Product);

2.7. Uso de arrays

Los contenedores tipo ArrSt y ArrPt también son reconocidos por DBind y, por tanto, pueden formar parte de los campos en una estructura registrada (Listado 12).

Listado 12: Uso de arrays con DBind.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
typedef struct _product_t
{
    ...
    ArrPt(Image) *images;
    ArrSt(Stock) *stocks;
} Product;

dbind(Product, ArrPt(Image)*, images);
dbind(Product, ArrSt(Stock)*, stocks);

// Create an object with inner arrays
Product *prod = dbind_create(Product);

// Create an array of registered objects
ArrSt(Product) *products = dbind_create(ArrSt(Product));

// Will destroy 'images' and 'stocks' arrays and its elements.
dbind_destroy(&prod, Product);
// Will destroy 'products' array and its elements.
dbind_destroy(&products, ArrSt(Product));

Un dato importante, que no debemos pasar por alto, es que los contenedores de tipo ArrSt solo pueden ser utilizados para tipos "abiertos", donde es conocida su definición y, por tanto, la memoria que necesita reservar el contenedor para cada elemento. Para tipos binarios u opacos (String, Image, MyType, etc) deberemos utilizar contenedores ArrPt que contienen punteros a objetos.

2.8. Valores por defecto

  • Utiliza dbind_default para establecer los valores por defecto de los campos de un objeto.

Hemos comentado anteriormente que, cuando creamos un objeto registrado, sus campos se inicializan con los valores por defecto, que mostramos en defaultval.

Tabla 1: Valores por defecto.
Tipo Valor
Booleanos FALSE
Enteros 0
Reales 0.0
Enumerados El valor mínimo (no tiene porqué ser 0).
String Cadena vacía "", (no NULL).
Objetos Valores por defecto de cada campo.
Objetos (punteros) Reserva de memoria y valores por defecto de cada campo.
Binarios NULL
Contenedores Se crea contenedor con 0 elementos.

Es posible cambiar estos valores para cada campo de un objeto (Listado 13). Además de valores por defecto para tipos básicos, podemos establecer "objetos anidados por defecto" o "contenedores por defecto" para cada nueva instancia que se cree o inicialice con DBind.

Listado 13: Establecer valores por defecto.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Defaults of basic types
dbind_default(Product, type_t, type, ekHDD);
dbind_default(Product, real32_t, price, 100.0f);

// Defaults of strings
// NULL is allowed
dbind_default(Product, String*, desc, "Empty-desc");
dbind_default(Product, String*, desc, NULL);

// Defaults of binaries
// NULL is allowed
Image *empty_icon = get_image("empty");
dbind_default(Product, Image*, image, empty_icon);
dbind_default(Product, Image*, image, NULL);
dbind_destroy(&empty_icon, Image);

// Defaults of static nested objects
// NULL is NOT allowed
Stock *defstock = get_default_stock();
dbind_default(Product, Stock, stock1, defstock);
dbind_destroy(&defstock, Stock);

// Defaults of dynamic nested objects
// NULL is allowed
dbind_default(Product, Stock, stock2, defstock);
dbind_default(Product, Stock, stock2, NULL);

// Defaults of containers
// NULL is allowed
ArrSt(Stock) *defstocks = get_3_locations_stocks();
dbind_default(Product, ArrSt(Stock)*, stocks, defstocks);
dbind_destroy(&defstocks, ArrSt(Stock));

2.9. Rangos numéricos

  • Utiliza dbind_range para establecer un máximo y mínimo en valores numéricos.
  • Utiliza dbind_precision para establecer la precisión en valores reales.
  • Utiliza dbind_increment para establecer el valor de incrementos discretos.
  • Utiliza dbind_suffix para establecer un sufijo que será añadido al convertir los números a texto.

Para concluir con las opciones de inicialización, DBind nos permite filtrar y acotar automáticamente los valores relacionados con campos numéricos uint32_t, int8_t, real64_t, etc (Listado 14). Internamente se encargará de validar los datos cada vez que se lean valores desde cualquier origen de datos (GUI, JSON, Streams, etc).

Listado 14: Rango y precisión del valor price.
1
2
3
4
dbind_range(Product, real32_t, price, .50f, 10000f);
dbind_precision(Product, real32_t, price, .01f);
dbind_increment(Product, real32_t, price, 5.f);
dbind_suffix(Product, real32_t, price, "€");

3. Comparación de objetos con DBind

  • Utiliza dbind_cmp para comparar dos objetos.
  • Utiliza dbind_equ para comprobar si dos objetos son iguales.

Realizar una comparación "profunda" de objetos puede tener asociada gran cantidad de trabajo, sobre todo en objetos grandes con anidaciones o contenedores. DBind proporciona esta función para cualquier tipo registrado (Listado 15). Ver Comparadores y claves.

Listado 15: Comparación de objetos con DBind.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
static int i_cmp(const Product *pr1, const Product *pr2)
{
    return dbind_cmp(pr1, pr2, Product);
}

ArrPt(Product) *products = create_products();
...
arrpt_sort(product, i_cmp, Product);
...
const Product *pr1 = get_product1();
const Product *pr2 = get_product1();
if (dbind_equ(pr1, pr2, Product) == TRUE)
{
    // 'pr1' and 'pr2' are equals
}

La relación de orden establecida por dbind_cmp() es de menor a mayor, lo que se traduce en:

  • Para tipos numéricos devolverá -1 si el primer elemento es menor, 1 si el primer elemento es mayor y 0 si son iguales.
  • Para cadenas de texto, realizará una comparación alfabética carácter a carácter, devolviendo -1, 1 al encontrar la primera discrepancia, o 0 si ambas cadenas son totalmente iguales.
  • Para arrays, primero comparará el número de elementos de cada contenedor, considerando "menor" el que menos elementos tenga. En caso de que este número coincida, se realizará una comparación elemento a elemento hasta encontrar el primer "no igual".
  • Para objetos anidados, realizará una comparación recursiva campo a campo en el orden en que se declaran en el struct. Devolverá 0 solo en el caso de que todos los campos sean iguales.

4. Serialización con DBind

  • Utiliza dbind_read para leer objeto desde un stream.
  • Utiliza dbind_write para escribir un objeto en un stream.

Otra gran ventaja de ofrece DBind en la serialización automática de objetos registrados, al conocer la composición detallada de cada tipo de dato. Por lo tanto, es posible acceder a los canales de E/S sin que sea necesario programar explícitamente funciones de escritura y lectura, como hacíamos en Serialización de arrays (Listado 16) (Figura 3).

Listado 16: Serialización de objetos con DBind.
1
2
3
ArrPt(Product) *products = dbind_read(stream, ArrPt(Product));
...
dbind_write(stream, products, ArrPt(Product));
Acceso a las tablas de dbind para serializar objetos.
Figura 3: Lectura/Escritura de objetos mediante DBind.

5. Importar y exportar a JSON

DBind ofrece un API privado para que módulos externos accedan a la información del registro y aprovechen toda la potencia que ofrece la vinculación de datos. Uno de estos módulos es JSON (Figura 4) que permite exportar (Listado 17) e importar (Listado 18) objetos de tipos registrados de forma automática sin ningún esfuerzo adicional. En (Listado 19) vemos un fragmento del archivo JSON generado.

Listado 17: Exportar a JSON con DBind.
1
2
3
4
ArrSt(Product) *products = dbind_create(ArrSt(Product));
...
Stream *stream = stm_to_file("data.json", NULL);
json_write(stream, products, NULL, ArrSt(Product));
Listado 18: Importar desde JSON con DBind.
1
2
3
4
5
Stream *stream = http_dget("http://mywebservice.com/dproducts.php", NULL, NULL);
ArrSt(Product) *products = json_read(stream, NULL, ArrSt(Product));
// 'products' is now a DBind-known object
...
dbind_destroy(&products, ArrSt(Product));
Listado 19: JSON generado a partir de ArrSt(Product).
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
[
  {
    "code":"i7-8700K",
    "desc":"Intel BX80684I78700K 8th Gen Core i7-8700K Processor",
    "type":0,
    "price":374.8899999999999863575794734060764312744140625,
    "image":"\/9j\/4AAQSkZJRgABAQ....
  },
  {
    "code":"G3900",
    ...
  }
    ...
}
Conexiones entre los campos de un objeto y un script JSON.
Figura 4: Data Binding en el análisis de scripts JSON.

6. Sincronización con interfaces gráficas

Y, por último, el uso principal que tradicionalmente se le ha dado a la vinculación de datos: La posibilidad de sincronizar la interfaz gráfica con los objetos que forman el modelo de datos. Este paradigma es conocido como MVVM (Model-View-ViewModel) (Figura 5) y utiliza los tipos Layout y Cell para asociar instancias y campos de struct respectivamente. Más información en GUI Data binding.

Conexiones entre una interfaz gráfica de usuario y los datos que manipula.
Figura 5: Sincronización automática de datos e interfaz gráfica.
❮ Anterior
Siguiente ❯

dbind ()

Añade un campo de una estructura a su tabla interna dentro de DBind.

dbindst_t
dbind(type,
      mtype,
      name);
type

Tipo de la estructura.

mtype

Tipo del campo a registrar.

name

Nombre del campo dentro de la estructura.

Retorna

Resultado del registro.


dbind_enum ()

Registra un valor tipo enum.

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

Tipo del enum.

value

Valor.

alias

Alias para el valor.

Retorna

Resultado del registro.

Observaciones

dbind_enum(mode_t, ekIMAGE_ANALISYS, "Image Analisys") utilizará la cadena "Image Analisys" en lugar de "ekIMAGE_ANALISYS" para aquellas operaciones E/S o de interfaz que requieran mostrar los literales del enumerado. Por ejemplo, para rellenar los campos de un PopUp vinculado con un campo de datos.


dbind_binary ()

Registra un tipo binario (opaco).

dbindst_t
dbind_binary(type,
             FPtr_copy func_copy,
             FPtr_read func_read,
             FPtr_write func_write,
             FPtr_destroy func_destroy);
type

Tipo del objeto.

func_copy

Función de copia.

func_read

Función de lectura.

func_write

Función de escritura.

func_destroy

Función de destrucción.

Retorna

Resultado del registro.

Observaciones

Ver Objetos binarios.


dbind_alias ()

Registra un alias para un tipo de datos (typedef).

dbindst_t
dbind_alias(type,
            alias);
type

Tipo del objeto.

alias

Nombre del alias.

Retorna

Resultado del registro.

Observaciones

Ver Alias de tipos.


dbind_unreg ()

Elimina un tipo de datos del registro DBind.

dbindst_t
dbind_unreg(type);
type

Tipo del objeto.

Retorna

Resultado de la eliminación.


dbind_create ()

Crea un objeto de tipo registrado, inicializando sus campos con los valores por defecto.

type*
dbind_create(type);
type

Tipo de objeto.

Retorna

Objeto recién creado o NULL si DBind no reconoce el tipo de dato.

Observaciones

Ver Creación de objetos.


dbind_copy ()

Copia un objeto de tipo registrado.

type*
dbind_copy(const type *obj,
           type);
obj

Objeto a copiar.

type

Tipo de objeto.

Retorna

Copia del objeto o NULL si DBind no reconoce el tipo de dato.

Observaciones

Ver Copia de objetos.


dbind_init ()

Inicializa los campos de un objeto de tipo registrado con los valores por defecto.

void
dbind_init(type *obj,
           type);
obj

Objeto cuya memoria ha sido reservada, pero no inicializada.

type

Tipo de objeto.

Observaciones

Ver Inicialización de objetos.


dbind_remove ()

Libera la memoria reservada por los campos de un objeto de tipo registrado, pero no destruye el objeto en sí.

void
dbind_remove(type *obj,
             type);
obj

Objeto.

type

Tipo de objeto.

Observaciones

Ver Inicialización de objetos.


dbind_destroy ()

Destruye un objeto de tipo registrado. La memoria asignada a los campos y sub-objetos también será liberada de forma recursiva.

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

Objeto. Será puesto a NULL tras la destrucción.

type

Tipo de objeto.

Observaciones

Ver Creación de objetos.


dbind_destopt ()

Destructor opcional. Igual que dbind_destroy, pero aceptando que el objeto sea NULL.

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

Objeto.

type

Tipo de objeto.


dbind_cmp ()

Compara dos objetos de tipo registrado.

int
dbind_cmp(const type *obj1,
          const type *obj2,
          type);
obj1

Primer objeto a comparar.

obj2

Segundo objeto a comparar.

type

Tipo de objeto.

Retorna

-1, 1 o 0 si obj1 es menor, mayor o igual que obj2.

Observaciones

Ver Comparación de objetos con DBind.


dbind_equ ()

Comprueba si dos objetos de tipo registrado son iguales.

bool_t
dbind_equ(const type *obj1,
          const type *obj2,
          type);
obj1

Primer objeto a comparar.

obj2

Segundo objeto a comparar.

type

Tipo de objeto.

Retorna

TRUE si son iguales.

Observaciones

Ver Comparación de objetos con DBind.


dbind_read ()

Crea un objeto de tipo registrado a partir de los datos leídos desde un stream.

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

Stream de lectura.

type

Tipo del objeto a leer.

Retorna

Objeto recién creado o NULL si ha habido algún error.

Observaciones

Ver Serialización con DBind.


dbind_write ()

Escribe el contenido de un objeto de tipo registrado en un stream de escritura.

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

Stream de escritura.

obj

Objeto a escribir.

type

Tipo del objeto a escribir.

Observaciones

Ver Serialización con DBind.


dbind_default ()

Establece el valor por defecto de un campo.

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

Tipo de la estructura.

mtype

Tipo del campo.

name

Nombre del campo dentro de la estructura.

value

Valor por defecto a partir de ahora.

Observaciones

Ver Valores por defecto.


dbind_range ()

Establece el valor máximo y mínimo en campos numéricos.

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

Tipo de la estructura.

mtype

Tipo del campo.

name

Nombre del campo dentro de la estructura.

min

Valor mínimo.

max

Valor máximo.

Observaciones

Ver Rangos numéricos.


dbind_precision ()

Establece el salto entre dos valores reales consecutivos.

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

Tipo de la estructura.

mtype

Tipo del campo.

name

Nombre del campo dentro de la estructura.

prec

Precisión (p.e. .05f en valores real32_t).

Observaciones

Ver Rangos numéricos.


dbind_increment ()

Establece el incremento de un valor numérico, por ejemplo, al pulsar en un control UpDown.

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

Tipo de la estructura.

mtype

Tipo del campo.

name

Nombre del campo dentro de la estructura.

incr

Incremento.

Observaciones

Ver Rangos numéricos.


dbind_suffix ()

Establece un sufijo que será añadido al valor numérico al convertirlo a texto.

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

Tipo de la estructura.

mtype

Tipo del campo.

name

Nombre del campo dentro de la estructura.

suffix

Sufijo.

Observaciones

Ver Rangos numéricos.

❮ Anterior
Siguiente ❯