흔히들 c 로 뭘 하는 것이 어렵게 느껴질 수도 있겠지만, 자꾸 쓰다보면, 엔간한거는 그냥 만들어쓰게 됩니다.

자바에 Observer 라는 패턴이 있고, Listener interface 도 있습니다. 서로 비슷합니다.

c 에는 그런게 없는데, 그냥 만들어 쓰면 됩니다. 자, 다음을 보시죠.

g_signal_connect (object, "signal1", func, user_data); 이러한 glib 함수가 있습니다.

이러한 일을 하는 코드를 어떻게 작성하는지 보여드리겠습니다. print_message*(), main() 함수를 제외하면,

50줄 정도 밖에 안 됩니다. 함수 이름을 원리를 이해하기 쉬우라고 observer_add_observer() 이렇게 했는데,

observer_signal_connect() 이렇게 정하면 더욱 그럴싸 하겠죠?


#include

#include


enum {

  SIGNAL1,

  SIGNAL2,

  LAST

};


typedef struct

{

  void (**callbacks[LAST]) (void);

  int     callbacks_len[LAST];

} Observer;


void observer_add_observer (Observer *observer, int signal, void *func)

{

  observer->callbacks[signal][observer->callbacks_len[signal]] = func;

  observer->callbacks_len[signal]++;

  observer->callbacks[signal] = realloc (

    observer->callbacks[signal],

    sizeof (void *) * (observer->callbacks_len[signal] + 1));

}


void observer_notify (Observer *observer, int signal)

{

  for (int i = 0; observer->callbacks[signal][i]; i++)

    observer->callbacks[signal][i]();

}


Observer *observer_new ()

{

  Observer *observer;


  observer = calloc (1, sizeof (Observer));


  for (int i = 0; i

    observer->callbacks[i] = calloc (1, sizeof (void *));


  return observer;

}


void observer_free (Observer *observer)

{

  for (int i = 0; i

    free (observer->callbacks[i]);


  free (observer);

}


void print_message1 ()

{

  puts ("This is a test1");

}


void print_message2 ()

{

  puts ("This is a test2");

}


void print_message3 ()

{

  puts ("This is a test3");

}


void print_message4 ()

{

  puts ("This is a test4");

}


int main (int argc, char **argv)

{

  Observer *observer;


  observer = observer_new ();


  observer_add_observer (observer, SIGNAL1, print_message1);

  observer_add_observer (observer, SIGNAL1, print_message2);

  observer_add_observer (observer, SIGNAL2, print_message3);

  observer_add_observer (observer, SIGNAL2, print_message4);


  observer_notify (observer, SIGNAL1);

  observer_notify (observer, SIGNAL2);


  observer_free (observer);


  return 0;

}