2020-11-24 10:37:36 +11:00
|
|
|
\chapter{Plugins}
|
2021-04-16 07:50:39 +11:00
|
|
|
\index{plugin}
|
2020-11-24 10:37:36 +11:00
|
|
|
|
2021-09-17 03:31:11 +11:00
|
|
|
% ------------------------------------
|
2020-11-24 10:37:36 +11:00
|
|
|
|
2021-09-17 03:31:11 +11:00
|
|
|
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
|
|
|
|
|
2022-04-03 20:56:49 +11:00
|
|
|
Une bibliothèque partagé (aka \texttt{.so}) est une collection
|
|
|
|
de fonctions, chargée une seule fois en mémoire centrale,
|
|
|
|
mais qui peut être utilisée par plusieurs programmes en
|
|
|
|
même temps.\index{.so}
|
2021-09-17 03:31:11 +11:00
|
|
|
Et c'est en partie sur ce concept qu'est basé le premier
|
2022-04-03 20:56:49 +11:00
|
|
|
mécanisme que nous allons découvrir~:
|
2021-09-17 03:31:11 +11:00
|
|
|
\texttt{dlopen} et sa petite famille.
|
|
|
|
|
|
|
|
% ------------------------------------
|
|
|
|
|
2022-04-03 20:56:49 +11:00
|
|
|
\section{Mécanisme}
|
2021-09-17 03:31:11 +11:00
|
|
|
|
2022-04-03 20:56:49 +11:00
|
|
|
\index{dlopen} \index{dlclose}
|
2021-09-17 03:31:11 +11:00
|
|
|
|
|
|
|
\texttt{dlclose, dlopen, dlmopen - open and close a shared object}
|
2021-04-16 07:50:39 +11:00
|
|
|
|
|
|
|
\begin{quote}
|
2022-04-03 20:56:49 +11:00
|
|
|
The function dlopen() loads the dynamic shared object (shared library)
|
2021-04-16 07:50:39 +11:00
|
|
|
file named by the null-terminated string filename and returns an opaque
|
2022-04-03 20:56:49 +11:00
|
|
|
"handle" for the loaded object. This handle is employed with other
|
|
|
|
functions in the dlopen API, such as dlsym(3), dladdr(3), dlinfo(3),
|
2021-04-16 07:50:39 +11:00
|
|
|
and dlclose().
|
|
|
|
\end{quote}
|
2020-11-24 10:37:36 +11:00
|
|
|
|
2022-04-03 20:56:49 +11:00
|
|
|
Traduit en clair, la fonction \texttt{dlopen} permet de charger
|
2023-11-30 00:12:03 +11:00
|
|
|
manuellement une bibliothèque partagée (un \texttt{.so})
|
|
|
|
en mémoire centrale, au lieu de
|
2022-04-03 20:56:49 +11:00
|
|
|
laisser faire le loader (ld.so) automatiquement au lancement
|
|
|
|
d'un binaire. la fonction \texttt{dlclose} va, elle, vidanger
|
|
|
|
la zone mémoire dans laquelle est le plugin.
|
|
|
|
|
|
|
|
|
2021-09-17 03:31:11 +11:00
|
|
|
% ------------------------------------
|
|
|
|
|
2020-11-24 10:37:36 +11:00
|
|
|
\section{Un exemple ?}
|
2021-09-17 03:53:40 +11:00
|
|
|
\label{ex_dlopen}
|
2020-11-24 10:37:36 +11:00
|
|
|
|
2021-09-17 03:31:11 +11:00
|
|
|
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
|
2022-04-03 20:56:49 +11:00
|
|
|
dans un fichier \textsc{.c} indépendant
|
|
|
|
(ci-après dénommé «le plugiciel») et qui
|
2021-09-17 03:31:11 +11:00
|
|
|
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
|
2023-11-30 00:12:03 +11:00
|
|
|
lecteurs, mais seulement à titre d'exercice.
|
2021-09-17 03:31:11 +11:00
|
|
|
|
|
|
|
\lstinputlisting[language=c]{code/plugiciel.c}
|
|
|
|
|
2022-04-03 20:56:49 +11:00
|
|
|
On peut difficilement faire plus simple pour une première
|
|
|
|
approche, mais attendez la suite des opérations,
|
|
|
|
la cinquième va vous étonner.
|
2021-09-17 03:53:40 +11:00
|
|
|
|
2021-09-17 03:31:11 +11:00
|
|
|
\subsection{L'appelant}
|
|
|
|
|
2022-04-03 20:56:49 +11:00
|
|
|
Voyons maintenant comment mettre ça en œuvre depuis le programme
|
|
|
|
principal.
|
|
|
|
Nous supposerons que le binaire du plugin est dans le répertoire
|
2023-11-30 00:12:03 +11:00
|
|
|
courant. Pour les autres cas, il faut jouer avec la variable
|
|
|
|
d'environnement \texttt{LD\_LIBRARY\_PATH} (cf man dlopen(3)) ou
|
|
|
|
le fichier \texttt{/etc/ld.so.cache} (cf man ldconfig(8)).
|
2021-09-17 03:31:11 +11:00
|
|
|
|
|
|
|
\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 *);}
|
|
|
|
|
2021-09-17 03:53:40 +11:00
|
|
|
\subsection{Le run}
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
tth@fubar:~/Documents/TetaTricks/code$ make plugin
|
|
|
|
gcc -Wall -shared -fPIC plugiciel.c -o plugiciel.so
|
|
|
|
gcc -Wall appelant.c -ldl -o appelant
|
|
|
|
tth@fubar:~/Documents/TetaTricks/code$ ./appelant
|
|
|
|
rgb * a = : 6.685000 8.320000 1.570795
|
|
|
|
tth@fubar:~/Documents/TetaTricks/code$
|
|
|
|
\end{verbatim}
|
2021-09-17 03:31:11 +11:00
|
|
|
|
|
|
|
% ------------------------------------
|
|
|
|
|
|
|
|
\section{Autres langages}
|
2020-11-24 10:37:36 +11:00
|
|
|
|
2022-04-03 20:56:49 +11:00
|
|
|
En Perl\index{Perl} ?
|
2021-04-16 07:50:39 +11:00
|
|
|
|
2022-04-03 20:56:49 +11:00
|
|
|
En Fortran\index{Fortran} ?
|
2021-04-16 07:50:39 +11:00
|
|
|
|
|
|
|
% -------------- to be continued
|
|
|
|
|