Lenguaje de programación C

CURLOPT_WRITEFUNCTION y CURLOPT_WRITEDATA para libcurl en C

En este artículo voy a hablar sobre la opción CURLOPT_WRITEFUNCTION que existe al usar libcurl en el lenguaje de programación C.

Esta función se encargará de recibir los datos, pero tiene una particularidad y es que dicha función podría ser llamada al menos 1 vez, hasta una cantidad de veces indefinidas. En cada llamada se le pasará una cierta cantidad de datos, a veces pueden ser todos, a veces solo una parte, y nosotros debemos estar preparados para recibirlos y almacenarlos en algún lugar.

Por cierto, el callback por defecto en esta opción es fwrite que simplemente imprime los datos.

Yo te mostraré un ejemplo para almacenar todos los datos en una cadena dinámica, ya que al tener una cadena dinámica vas a poder compararla, imprimirla o almacenarla en algún lugar.

Cadena dinámica

No siempre vamos a necesitar los datos como cadena. Puede que al descargar un archivo binario simplemente necesitemos escribir los bytes así como los vamos recibiendo, sin embargo en mi caso particular necesito leer la respuesta HTTP como una cadena así que implementé mi propia estructura de datos para tener una cadena dinámica.

Aquí voy a usar ese struct pero no explicaré su funcionamiento, ya que eso está en su propio post: implementación de cadena dinámica en C.

Iniciando datos

Comenzamos inicializando la cadena vacía:

struct Cadena *miCadena = (struct Cadena *)malloc(sizeof(struct Cadena));
if (miCadena == NULL)
{
 printf("Sin memoria suficiente para alojar el struct de cadena");
 return EXIT_FAILURE;
}
iniciarCadena(miCadena);

Y ahora ya podemos concatenar sin límite:

void concatenar(struct Cadena *cadena, char *otraCadena)
{
 size_t longitudDeOtraCadena = strlen(otraCadena);
 size_t nuevaLongitud = cadena->longitud + longitudDeOtraCadena;
 size_t nuevaLongitudConByteNulo = nuevaLongitud + 1;
 size_t longitudDeOtraCadenaIncluyendoByteNulo = longitudDeOtraCadena + 1;
 char *cadenaConNuevaLongitud = realloc(cadena->datos, nuevaLongitudConByteNulo);
 if (cadenaConNuevaLongitud == NULL)
 {
  printf("Sin memoria suficiente para concatenar la nueva cadena");
  return;
 }
 cadena->datos = cadenaConNuevaLongitud;
 memcpy((char *)(cadena->datos + cadena->longitud), otraCadena, longitudDeOtraCadenaIncluyendoByteNulo);
 cadena->longitud = nuevaLongitud;
}

Función de escritura

Después definimos la función write_callback que recibe el fragmento de datos y concatenamos los datos a la cadena, asumiendo que los datos devueltos son de tipo cadena:

size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp)
{
 // Esta función podría ser invocada varias veces por cURL. https://curl.se/libcurl/c/CURLOPT_WRITEFUNCTION.html
 size_t realsize = size * nmemb;
 concatenar((struct Cadena *)userp, (char *)contents);
 concatenar((struct Cadena *)userp, "");
 return realsize;
}

Finalmente indicamos dicha función en CURLOPT_WRITEFUNCTION y pasamos el apuntador a dicha cadena en CURLOPT_WRITEDATA así:

struct Cadena *miCadena = (struct Cadena *)malloc(sizeof(struct Cadena));
if (miCadena == NULL)
{
 printf("Sin memoria suficiente para alojar el struct de cadena");
 return EXIT_FAILURE;
}
iniciarCadena(miCadena);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)miCadena);

De este modo, la respuesta será almacenada en la estructura de datos de la cadena dinámica. Es un ejemplo simple y sencillo sobre cómo usar CURLOPT_WRITEDATA – pointer passed to the write callback y CURLOPT_WRITEFUNCTION – callback for writing received data.

Más adelante te mostraré el ejemplo de una petición GET y POST que utilizan esta función para recibir los datos, pero era necesario colocar por separado esa función ya que aplica lo mismo para todos los tipos de petición.

Actualización

Ya están publicados los artículos con ejemplos para hacer una petición POST con C y para hacer una petición GET con ANSI C igualmente.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.
parzibyte

Programador freelancer listo para trabajar contigo. Aplicaciones web, móviles y de escritorio. PHP, Java, Go, Python, JavaScript, Kotlin y más :) https://parzibyte.me/blog/software-creado-por-parzibyte/

Entradas recientes

Servidor HTTP en Android con Flutter

El día de hoy te mostraré cómo crear un servidor HTTP (servidor web) en Android…

3 días hace

Imprimir automáticamente todos los PDF de una carpeta

En este post te voy a enseñar a designar una carpeta para imprimir todos los…

4 días hace

Guía para imprimir en plugin versión 1 desde Android

En este artículo te voy a enseñar la guía para imprimir en una impresora térmica…

1 semana hace

Añadir tasa de cambio en sistema de información

Hoy te voy a mostrar un ejemplo de programación para agregar un módulo de tasa…

2 semanas hace

Comprobar validez de licencia de plugin ESC POS

Los usuarios del plugin para impresoras térmicas pueden contratar licencias, y en ocasiones me han…

2 semanas hace

Imprimir euro € en impresora térmica

Hoy voy a enseñarte cómo imprimir el € en una impresora térmica. Vamos a ver…

3 semanas hace

Esta web usa cookies.