2010-05-21 14 views
6

Przeglądałem, pisząc mały framework IRC w C, który teraz zamierzam rozszerzyć z pewną podstawową funkcjonalnością - ale poza tym chciałbym, żeby było rozszerzalne z wtyczkami !Architektura wtyczek w języku C przy użyciu biblioteki libdl

Do tej pory, gdy pisałem coś związanego z IRC (i dużo pisałem, w około 6 różnych językach teraz ... jestem w płomieniach!) I faktycznie poszedłem do przodu, aby zaimplementować architekturę wtyczek, to było w środku język interpretowany, który miał ułatwienia (czytaj: nadużywanie), tak jak zacina cały plik skryptu za pomocą eval w Ruby (złe!).

Teraz chcę nadużyć coś w C!

Zasadniczo tam trzy rzeczy mogłem zrobić

  1. zdefiniować prosty język skryptowy wewnątrz mojego programu
  2. użyć istniejącego, osadzanie tłumacza
  3. użytkowania libdl załadować * .so modułów na starcie

Ja lubię trzeci i raather unikaj dwóch pozostałych opcji, jeśli to możliwe. Może jestem pewnego rodzaju masochistą, ale myślę, że może to być zarówno zabawne, jak i użyteczne dla celów edukacyjnych.

Logiczne myślenie, oczywisty "łańcuch bólu" będzie (najniższy lub najwyższy) 2 -> 1 -> 3, z prostej przyczyny, że libdl ma do czynienia z surowym kodem, który może (i będzie) eksplodować na mojej twarzy częściej niż nie.

Więc to pytanie wychodzi do ciebie, inni użytkownicy stackoverflow, myślisz, że libdl jest do tego zadania, a nawet realistyczna myśl?

Odpowiedz

3

libdl jest bardzo dobrze dostosowany do architektury wtyczek - w określonych granicach :-). Jest używany bardzo dokładnie w tym celu w wielu różnych programach. Działa dobrze w sytuacjach, w których istnieje dobrze zdefiniowany interfejs API/interfejs między programem głównym a wtyczką, a wiele różnych wtyczek implementuje ten sam interfejs API/interfejs. Na przykład twój klient IRC może mieć wtyczki, które implementują bramy do różnych protokołów IM (Jabber, MSN, Sametime itp.) - wszystkie są bardzo podobne, więc możesz zdefiniować API z funkcjami takimi jak "wyślij wiadomość "," sprawdź odpowiedź "itd. - i napisz kilka wtyczek, z których każdy zaimplementował inny protokół.

Sytuacja, w której działa gorzej, polega na tym, że chcesz, aby wtyczki dokonywały dowolnych zmian w zachowaniu głównego programu - w taki sposób, że na przykład wtyczki Firefox mogą zmieniać zachowanie przeglądarki karty, ich wygląd, przyciski dodawania/usuwania itp. Tego typu rzeczy są dużo łatwiejsze do osiągnięcia w dynamicznym języku (stąd duża część Firefoksa jest zaimplementowana w javascript), a jeśli jest to rodzaj dostosowania, który chcesz, możesz być lepiej z twoją opcją (2) i napisać dużo twojego interfejsu w języku skryptowym ...

+0

Zmiany w głównej funkcji nie działają - po prostu zaimplementowałem funkcje takie jak "on_channel_message (...)" - na inną myśl .. czy biblioteki mogą być załadowane funkcjami dostępu do libdl zdefiniowanymi w głównym programie? – LukeN

+0

Czasami mogą, ale najbezpieczniej jest założyć, że nie (ponieważ (a) czasami trzeba przekazać specjalne flagi kompilacji, aby je włączyć, oraz (b) na ogół nie chcesz, aby działały z dowolnymi funkcjami w głównym programie!). Zwykle najlepiej jest przekazać strukturę zawierającą listę wskaźników funkcji, które wtyczka może wywoływać. – psmears

1

Istnieje wiele istniejących programów C, które używają dlopen()/dlsym() do implementacji architektury wtyczek (w tym więcej niż jednej związanej z IRC); więc tak, to zdecydowanie zależy od zadania.

3

dlopen()/dlsym() to prawdopodobnie najłatwiejszy sposób.Niektóre głupie kod psuedo:

int run_module(const char *path, char **args) 
{ 
    void *module; 
    void (*initfunc)(char **agrs); 
    int rc = 0; 

    module = dlopen(path, RTLD_NOW); 
    if (module == NULL) 
     err_out("Could not open module %s", path); 

    initfunc = dlsym(module, "module_init"); 
    if (initfunc == NULL) { 
     dlclose(module); 
     err_out("Could not find symbol init_func in %s", path); 
    } 

    rc = initfunc(args); 

    dlclose(module); 

    return rc; 
} 

można byłoby, oczywiście, chcą znacznie bardziej w sposób sprawdzania błędów, a także kod, który faktycznie coś pożytecznego :) Jest jednak niezwykle łatwe i wygodne napisz architekturę wtyczki wokół pary i opublikuj łatwą specyfikację, aby inni mogli zrobić to samo.

Prawdopodobnie chciałbyś czegoś więcej na wzór load_module(), powyższe ładuje tylko SO, szuka punktu wejścia i blokuje, aż ten punkt wejścia zostanie zamknięty.

To nie znaczy, że pisanie własnego języka skryptowego to zły pomysł. Ludzie mogą pisać skomplikowane filtry, reagować, itp. Bez konieczności przechodzenia przez wiele kłopotów. Być może obie będą dobrym pomysłem. Nie wiem, czy chciałbyś mieć pełnoprawnego tłumacza LUA ... może uda ci się wymyślić coś, co sprawia, że ​​podejmowanie działań opartych na prostych wyrażeniach jest proste.

Mimo to podłączanie modułów nie tylko uprości Twoje życie, ale także pomoże ci rozwinąć społeczność ludzi rozwijających różne rzeczy.

Powiązane problemy