From d20a832a8d57ed1e12da44bcf9932375d59603ca Mon Sep 17 00:00:00 2001 From: tth Date: Thu, 16 Sep 2021 18:31:11 +0200 Subject: [PATCH] first working plugin demo --- .gitignore | 3 +++ chap/plugins.tex | 58 +++++++++++++++++++++++++++++++++++++++++++++--- code/Makefile | 10 ++++++++- code/appelant.c | 33 +++++++++++++++++++++++++++ code/plugiciel.c | 12 ++++++++++ code/plugiciel.h | 1 + 6 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 code/appelant.c create mode 100644 code/plugiciel.c create mode 100644 code/plugiciel.h diff --git a/.gitignore b/.gitignore index a256344..a34ed91 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ code/no-op code/get-signal code/fifo-tx code/fifo-rx +code/plugiciel.so +code/appelant + diff --git a/chap/plugins.tex b/chap/plugins.tex index f82e9db..6809552 100644 --- a/chap/plugins.tex +++ b/chap/plugins.tex @@ -1,9 +1,26 @@ \chapter{Plugins} \index{plugin} -\texttt{dlopen}\index{dlopen} +% ------------------------------------ -dlclose, dlopen, dlmopen - open and close a shared object +Le concept de bibliothèque partagée +(\textsl{shared library} en anglais est apparu, du moins +dans le monde Unix, avec \textsl{SunOS 4}, en 1989. +Mais il est probable que ce concept existait déja dans +d'autres mondes, peut-être avec \textsl{AmigaOS} ou +\textsl{VAX/VMS}\index{VMS}\dots + +Et c'est en partie sur ce concept qu'est basé le premier +mécanisme que nous allond écouvrir~: +\texttt{dlopen} et sa petite famille. + +% ------------------------------------ + +\section{Mécanique} + +\index{dlopen} + +\texttt{dlclose, dlopen, dlmopen - open and close a shared object} \begin{quote} The function dlopen() loads the dynamic shared object (shared library) @@ -13,9 +30,44 @@ functions in the dlopen API, such as dlsym(3), dladdr(3), dlinfo(3), and dlclose(). \end{quote} +% ------------------------------------ + \section{Un exemple ?} -XXX\index{XXX} +Comme d'habitude, je vais proposer un exemple un peu artificiel, +mais qui, de part sa simplicité, illustrera clairement +les concepts de base. Partons du principe que nous avons +un tableau de quatre nombres flottants, et que nous souhaitons +proposer un affichage de ce tableau modifiable à volonté. + +Nous allons donc écrire notre fonction personnelle d'affichage +dans un fichier \textsc{.c} indépendant (le plugiciel) et qui +sera chargé dynamiquement au \textsl{run-time} par le logiciel +principal (l'appelant). + +\subsection{Le plugiciel} + +C'est ici que nous trouverons le code actif de l'exemple, +l'utilité de notre \textsl{usecase} reste à déterminer par nos +lecteurs, à titre d'exercice. + +\lstinputlisting[language=c]{code/plugiciel.c} + +\subsection{L'appelant} + + + +\lstinputlisting[language=c]{code/appelant.c} + +Ah, les choses se corsent un peu, il y a un pointeur bien +tortueux à déchiffrer. Il était temps. + +\texttt{void (*funcname)(const char*, const float *);} + + +% ------------------------------------ + +\section{Autres langages} diff --git a/code/Makefile b/code/Makefile index 03c180b..598a4b7 100644 --- a/code/Makefile +++ b/code/Makefile @@ -19,7 +19,7 @@ arguments: arguments.c Makefile no-op: no-op.c Makefile gcc -Wall $< -o $@ -#------------- IPC +#------------- IPC ----------------------- get-signal: get-signal.c Makefile gcc -Wall $< -o $@ @@ -35,3 +35,11 @@ fifo-tx: fifo-tx.c my-fifo.h dtime.o Makefile fifo-rx: fifo-rx.c my-fifo.h dtime.o Makefile gcc -Wall $< dtime.o -o $@ +#------------- PLUGIN -------------------- + +plugiciel.so: plugiciel.c plugiciel.h Makefile + gcc -Wall -shared -fPIC $< -o $@ + +appelant: appelant.c plugiciel.h Makefile + gcc -Wall $< -ldl -o $@ + diff --git a/code/appelant.c b/code/appelant.c new file mode 100644 index 0000000..ba2e917 --- /dev/null +++ b/code/appelant.c @@ -0,0 +1,33 @@ +/* appelant.c */ + +#include +#include + +void affichage(char *titre, float vals[4]); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +int main(int argc, char *argv[]) +{ +void *handle; +float values[4]; + +void (*funcname)(const char*, const float *); + +handle = dlopen("./plugiciel.so", RTLD_LAZY); +if (!handle) { + /* fail to load the library */ + fprintf(stderr, "Error: %s\n", dlerror()); + return 1; + } + +*(void**)(&funcname) = dlsym(handle, "affichage"); + +values[0] = 13.37; values[1] = 16.64; +values[2] = 3.14159; values[3] = 0.5; + +funcname("rgb * a =", values); + +return 0; +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + diff --git a/code/plugiciel.c b/code/plugiciel.c new file mode 100644 index 0000000..0d1eada --- /dev/null +++ b/code/plugiciel.c @@ -0,0 +1,12 @@ +/* plugiciel.c */ + +#include +#include "plugiciel.h" + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +void affichage(char *titre, float vals[4]) +{ +printf("%s : %f %f %f\n", titre, + vals[0]*vals[3], vals[1]*vals[3], vals[2]*vals[3]); +} +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - */ diff --git a/code/plugiciel.h b/code/plugiciel.h new file mode 100644 index 0000000..38c47f6 --- /dev/null +++ b/code/plugiciel.h @@ -0,0 +1 @@ +void affichage(char *titre, float vals[4]);