[C] Lista dinámica de funciones en C (emulando los delegados de .NET)

Iniciado por MAFUS, 20 Diciembre 2015, 01:38 AM

0 Miembros y 1 Visitante están viendo este tema.

MAFUS

Muy buenas.

Pues la idea es hacer algo parecido a los delegados de C# pero con el C de toda la vida.
Sobre una lista dinámica de diferentes funciones con la misma firma se puede hacer las siguientes operaciones:
· Añadir funciones al final de la lista
· Quitar la primera aparición de una función dada
· Vaciar la lista de una tacada
· Ejecutar todas las funciones de la lista de forma secuencial y con unos parámetros comunes dados en la llamada a la ejecución.

En este programa se trabaja sobre una función que acepta un char* y no devuelve nada, pero se puede modificar fácilmente para trabajar con otras funciones.


#include <stdio.h>
#include <stdlib.h>

typedef struct tdelegate {
void (*func)(char*);
struct tdelegate *next;
} DELEGATE;

int delegate_add(DELEGATE **pdelegate, void (*funcpointer)(char*)) {
DELEGATE *newdelegate = malloc(sizeof(DELEGATE));
DELEGATE *aux = NULL;

if(newdelegate == NULL)
return 0;

newdelegate->func = funcpointer;
newdelegate->next = NULL;

if(*pdelegate == NULL)
*pdelegate = newdelegate;
else {
aux = *pdelegate;
while(aux->next != NULL)
aux = aux->next;
aux->next = newdelegate;
}
return 1;
}

void delegate_exec(DELEGATE **pdelegate, char *str) {
DELEGATE *actualdelegate = *pdelegate;

while(actualdelegate != NULL) {
actualdelegate->func(str);
actualdelegate = actualdelegate->next;
}
}

void delegate_del(DELEGATE **pdelegate, void (*funcpointer)(char*)) {
DELEGATE *actualdelegate = *pdelegate;
DELEGATE *aux = NULL;
int found = 0;

if(funcpointer == NULL || actualdelegate == NULL)
return;

if(actualdelegate->func == funcpointer)
{
aux = actualdelegate->next;
free(actualdelegate);
actualdelegate = aux;
}
else {
while(actualdelegate->next != NULL && !found) {
if(actualdelegate->next->func == funcpointer) {
found = 1;
aux = actualdelegate->next->next;
free(actualdelegate->next);
actualdelegate->next = aux;
}
else actualdelegate = actualdelegate->next;
}
}
}

void delegate_free(DELEGATE **pdelegate) {
DELEGATE *aux = NULL;

if(*pdelegate == NULL) return;
while(*pdelegate != NULL) {
aux = (*pdelegate)->next;
free(*pdelegate);
*pdelegate = aux;
}
}

/* FUNCIONES DE PRUEBA */
void a(char *str) {
printf("%p: %s\n", &a, str);
}

void b(char *str) {
printf("%p: %s\n", &b, str);
}

void c(char *str) {
printf("%p: %s\n", &c, str);
}

/* PROGRAMA DE PRUEBA */
int main() {

DELEGATE *midelegado = NULL;

delegate_add(&midelegado, &a);
delegate_add(&midelegado, &b);
delegate_add(&midelegado, &c);

delegate_exec(&midelegado, "hola");

delegate_del(&midelegado, &b);
delegate_exec(&midelegado, "adios");

delegate_free(&midelegado);
midelegado = NULL;

return 0;
}


kondrag_X1

muy bueno tenia en mente hacer algo parecido. Le echaré un ojo.  ;-)

MAFUS

Muy buenas!

Espero que te sirva  :D

Si desarrollas tu idea postea, tengo ganas de verla  :rolleyes: