\label{doc_decisions_0_drafts_plugin_contract_function_md_md_doc_decisions_0_drafts_plugin_contract_function}%
\Hypertarget{doc_decisions_0_drafts_plugin_contract_function_md_md_doc_decisions_0_drafts_plugin_contract_function}%
 \hypertarget{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1810}{}\doxysection{Problem}\label{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1810}
Contract for a plugin is currently retrieved by calling the plugin\textquotesingle{}s {\ttfamily get} function with a special {\ttfamily parent\+Key}. This makes the {\ttfamily get} function awkward to write. You must always first check for the special {\ttfamily parent\+Key}. It also makes the {\ttfamily get} function mandatory, even if the plugin doesn\textquotesingle{}t implement any real {\ttfamily get} functionality.

Additionally, the actual public API exported from shared library to make it a plugin is the {\ttfamily ELEKTRA\+\_\+\+PLUGIN\+\_\+\+EXPORT} function. This function always calls {\ttfamily elektra\+Plugin\+Export}, which allocates and half initializes a {\ttfamily struct \+\_\+\+Plugin}. Specifically, only the {\ttfamily name} field and the {\ttfamily kdb$\ast$} function pointers are set. This same information is also provided via the contract. The function pointers are all listed in {\ttfamily system\+:/elektra/modules/$<$plugin$>$/exports/$\ast$} and the {\ttfamily $<$plugin$>$} part of the name is the {\ttfamily name} of the plugin.\hypertarget{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1811}{}\doxysection{Constraints}\label{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1811}
\hypertarget{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1812}{}\doxysection{Assumptions}\label{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1812}
\hypertarget{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1813}{}\doxysection{Considered Alternatives}\label{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1813}

\begin{DoxyEnumerate}
\item Create a separate {\ttfamily kdb\+Contract} that returns the contract of a plugin.
\end{DoxyEnumerate}


\begin{DoxyCode}{0}
\DoxyCodeLine{KeySet * \mbox{\hyperlink{group__plugin_gacb05c902e4014535589db4193da87460}{ELEKTRA\_PLUGIN\_FUNCTION}}(contract) ();}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{comment}{// OR}}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keywordtype}{void} \mbox{\hyperlink{group__plugin_gacb05c902e4014535589db4193da87460}{ELEKTRA\_PLUGIN\_FUNCTION}}(contract) (KeySet * ks);}

\end{DoxyCode}


This solves the problem of the awkward {\ttfamily get} function, but it does not address the issue of the duplicate information in {\ttfamily ELEKTRA\+\_\+\+PLUGIN\+\_\+\+EXPORT}.


\begin{DoxyEnumerate}
\item Change the {\ttfamily ELEKTRA\+\_\+\+PLUGIN\+\_\+\+EXPORT} to return the contract of the plugin instead of creating half a {\ttfamily struct \+\_\+\+Plugin}.
\end{DoxyEnumerate}


\begin{DoxyCode}{0}
\DoxyCodeLine{KeySet * ELEKTRA\_PLUGIN\_EXPORT ();}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{comment}{// OR}}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keywordtype}{void} ELEKTRA\_PLUGIN\_EXPORT (KeySet * ks);}

\end{DoxyCode}


This also removes the duplicate information inside the plugin.


\begin{DoxyEnumerate}
\item (combined with 2) Change what the {\ttfamily Key\+Set $\ast$ modules} stores.

Currently, {\ttfamily modules} stores data dependent on how modules are loaded. When dynamic linking is used, the keys store the handle from {\ttfamily dlopen} and a pointer to the {\ttfamily ELEKTRA\+\_\+\+PLUGIN\+\_\+\+EXPORT} function. With static linking, the keys store a custom struct with function pointers.

Instead, we would now store the contracts directly in {\ttfamily Key\+Set $\ast$ modules}.

The implementations of {\ttfamily elektra\+Modules\+Load} would simply find the correct function and call it.
\end{DoxyEnumerate}


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{keyword}{typedef} void (*elektraPluginExportFn) (KeySet * ks);}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keywordtype}{void} elektraModulesLoad (KeySet * modules, \textcolor{keyword}{const} \textcolor{keywordtype}{char} * name, Key * errorKey)}
\DoxyCodeLine{\{}
\DoxyCodeLine{     Key * moduleKey = \mbox{\hyperlink{group__key_gad23c65b44bf48d773759e1f9a4d43b89}{keyNew}} (\textcolor{stringliteral}{"{}system:/elektra/modules"{}}, \mbox{\hyperlink{group__key_gga9b703ca49f48b482def322b77d3e6bc8aa8adb6fcb92dec58fb19410eacfdd403}{KEY\_END}});}
\DoxyCodeLine{\mbox{\hyperlink{group__keyname_gaa942091fc4bd5c2699e49ddc50829524}{keyAddBaseName}} (moduleKey, name);}
\DoxyCodeLine{\textcolor{keywordflow}{if} (\mbox{\hyperlink{group__keyset_ga60f1ddcf23272f2b29b90e92ebe9b56f}{ksLookup}} (modules, moduleKey, 0) != NULL)}
\DoxyCodeLine{\{}
\DoxyCodeLine{             \textcolor{comment}{// already loaded}}
\DoxyCodeLine{     \textcolor{keywordflow}{return};}
\DoxyCodeLine{\}}
\DoxyCodeLine{}
\DoxyCodeLine{     elektraPluginExportFn exportFn;}
\DoxyCodeLine{     \textcolor{comment}{// [...] find exportFn for plugin}}
\DoxyCodeLine{}
\DoxyCodeLine{     exportFn (modules); \textcolor{comment}{// inserts the contract with all the exported functions}}
\DoxyCodeLine{}
\DoxyCodeLine{     \textcolor{keywordflow}{if} (\mbox{\hyperlink{group__keyset_ga60f1ddcf23272f2b29b90e92ebe9b56f}{ksLookup}} (modules, moduleKey, 0) == NULL)}
\DoxyCodeLine{\{}
\DoxyCodeLine{             \mbox{\hyperlink{group__keyset_gaa5a1d467a4d71041edce68ea7748ce45}{ksAppendKey}} (modules, moduleKey);}
\DoxyCodeLine{\}}
\DoxyCodeLine{     \textcolor{keywordflow}{else}}
\DoxyCodeLine{     \{}
\DoxyCodeLine{             \mbox{\hyperlink{group__key_ga3df95bbc2494e3e6703ece5639be5bb1}{keyDel}} (moduleKey);}
\DoxyCodeLine{     \}}
\DoxyCodeLine{\}}

\end{DoxyCode}


\begin{quote}
{\bfseries{Note}} to avoid allocated and deleting a temporary {\ttfamily Key\+Set $\ast$} the {\ttfamily void ELEKTRA\+\_\+\+PLUGIN\+\_\+\+EXPORT (Key\+Set $\ast$ ks)} API works best here. \end{quote}
\hypertarget{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1814}{}\doxysection{Decision}\label{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1814}
\hypertarget{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1815}{}\doxysection{Rationale}\label{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1815}
\hypertarget{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1816}{}\doxysection{Implications}\label{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1816}
\hypertarget{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1817}{}\doxysection{Related Decisions}\label{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1817}

\begin{DoxyItemize}
\item \mbox{\hyperlink{doc_decisions_0_drafts_commit_function_md}{Commit Function}}
\item \mbox{\hyperlink{doc_decisions_0a_postponed_plugin_struct_md}{Plugin Struct}}
\end{DoxyItemize}\hypertarget{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1818}{}\doxysection{Notes}\label{doc_decisions_0_drafts_plugin_contract_function_md_autotoc_md1818}
