Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
codaz:c:dlopen_dlsym_et_plugins_en_c [2008/08/26 20:29]
jfg
codaz:c:dlopen_dlsym_et_plugins_en_c [2010/01/12 13:29] (current)
Line 1: Line 1:
 +===== Un système de plugins en C =====
  
 +L'​hiver approche, il serait temps de repilosifier votre fourrure.
 +C'est pour cela que je vous propose d'​étudier un système de plugins
 +orgianale en C.
 +
 +On a donc une application chargée de parser des messages et de les traiter
 +d'une manière ou d'une autre en fonction de leur contenu.
 +
 +Au bout d'un moment l'​appli devient monstrueuse mais on a besoin d'​ajouter encore
 +plein de features toussa toussa. On décide donc de la rendre pluggable.\\ ​
 +L'​orgianalité réside dans le fait qu'on va laisser les plugins "​informer"​ notre appli si c'est à eux
 +de prendre en charge le message ou pas (et non pas l'​appli qui décide quel plugin appeler).
 +
 +En gros :
 +   * Je reçois un message
 +   * Je le passe tour à tour à chaque plugin
 +   * Lorsqu'​un plugin rencontre un message qu'il connait, il le traite
 +   * Fin de la boucle, l'​appli peut faire des trucs moins "​spécialisés"​ sur le message
 +
 +\\ Les codes source qui vont suivre ne sont pas faits pour être beaux, mais pour être simples.\\ ​
 +<​philosophie_a_deux_roubles>​
 +Ce qui ne signifie pas que pour faire simple on doit obligatoirement faire moche.
 +</​philosophie_a_deux_roubles>​
 +
 +Je tiens avant tout à présenter mes tartiflettes et mon cassoulet pour la coloration syntaxique de ce wiki qui est, il faut le dire, abominable.
 +
 +== main.c ==
 +<code c>
 +#include <​stdio.h>​
 +#include <​stdlib.h>​
 +#include <​string.h>​
 +#include <​dlfcn.h>​
 +
 +typedef int my_func_t( char * foo, char * bar );
 +
 +typedef struct my_plugins_s
 +{
 +        char * libname;
 +        void * handle;
 +        my_func_t * func;
 +}
 +my_plugins_t;​
 +
 +my_plugins_t plugins[] = {
 +        { "​libchose.so",​ NULL, NULL },
 +        { "​libtruc.so",​ NULL, NULL },
 +        { NULL, NULL, NULL },
 +};
 +
 +char * chose = "CHOSE truc chouette";​
 +char * truc  = "​TRUC ​ chose chouette";​
 +char * autre = "AUTRE CHOSE TRUC POUET";​
 +char * rien;
 +
 +        int
 +openlibs( )
 +{
 +        int i;
 +        char * error;
 +
 +        for ( i=0; plugins[i].libname;​ ++i )
 +        {
 +                plugins[i].handle = dlopen( plugins[i].libname,​ RTLD_LAZY );
 +                if ( !plugins[i].handle ) {
 +                        fprintf( stderr, "​dlopen error : %s\n", dlerror() );
 +                        return -1;
 +                }
 +
 +                dlerror();
 +
 +                plugins[i].func = dlsym( plugins[i].handle,​ "​check_sc"​ );
 +                ​
 +                if ((error = dlerror()) != NULL )
 +                {
 +                        fprintf( stderr, "dlsym error : %s\n", error );
 +                        return -1;
 +                }
 +        }
 +        ​
 +        return 0;
 +}
 +
 +        void
 +closelibs()
 +{
 +        int i;
 +        for ( i=0; plugins[i].handle;​ ++i)
 +                dlclose( plugins[i].handle );
 +}
 +
 +        int
 +main( int argc, char **argv )
 +{
 +        int i;
 +        puts("​Main program starts ...");
 +
 +        if( ! openlibs() )
 +        {
 +                my_func_t check_sc;
 +                puts(" Trying une chose ...");
 +                for( i=0; plugins[i].func;​ ++i )
 +                        (plugins[i].func)( chose, rien );
 +                ​
 +                puts(" Trying un truc ...");
 +                for( i=0; plugins[i].func;​ ++i )
 +                        (plugins[i].func)( truc, rien );
 +
 +                puts(" Trying autre chose ...");
 +                for( i=0; plugins[i].func;​ ++i )
 +                        (plugins[i].func)( autre, rien );
 +        }
 +
 +        closelibs();​
 +
 +        return 0;
 +
 +}
 +</​code> ​    
 +
 +
 +
 +== libchose.c ==
 +
 +<code c>
 +#include <​stdio.h>​
 +#include <​string.h>​
 +
 +        int
 +check_sc( char * foo, char * bar )
 +{
 +        if ( ! strncmp( foo, "​CHOSE",​ 5 ) )
 +        {       
 +                puts(" ​  Il y a une chose !");
 +                return 0;
 +        }
 +        puts(" ​  Il n'y avait pas de chose."​);​
 +        return -1;
 +}
 +</​code>​
 +
 +== libtruc.c ==
 +<code c>
 +#include <​stdio.h>​
 +#include <​string.h>​
 +
 +        int
 +check_sc( char * foo, char * bar )
 +{
 +        if ( ! strncmp( foo, "​TRUC",​ 4 ) )
 +        {       
 +                puts(" ​  Il y a un truc !");
 +                return 0;
 +        }
 +        puts(" ​  Il n'y avait pas de truc."​);​
 +        return -1;
 +}
 +
 +</​code>​
 +
 +== compil.sh ==
 +<​code>​
 +#!/bin/sh
 +
 +export LD_LIBRARY_PATH="​.:"​
 +rm dynlib libchose.so libtruc.so &>/​dev/​null
 +gcc -shared -nostartfiles -o libchose.so libchose.c
 +gcc -shared -nostartfiles -o libtruc.so libtruc.c
 +gcc -rdynamic -o dynlib main.c -ldl
 +./dynlib
 +</​code>​
 +
 +
 +== Explications ==
 +
 +C'est trop pénible d'​expliquer :
 +man dlopen ​ (il y a un exemple et toutes les explications qu'il faut).
 +
 +Le reste, si on connaît le C et ses pointeurs de fonctions, se comprend aisément.
 +
 + --- //​[[jf.guchens@gmail.com|jfg]] 2008/08/26 22:14//
codaz/c/dlopen_dlsym_et_plugins_en_c.txt · Last modified: 2010/01/12 13:29 (external edit)