Applications depending on gpmi packages

1. Introduction

Usually an application uses gpmi to have modules that will later call application functions back trough application-specific packages. However some packages are not application-specific, but general ones to provide a way to access console, network or other resources for any module. Sometimes it's useful to utilize these applications from the host application as well. However, it's not as easy as it is from modules or other applications.

2. Problem: resolving references

When you link a module to form dynamic library, it is expected by the compiler that there will be (external) references that can't be resolved at the time of compiling or linking. For an application, it's different: the linker needs to resolve every reference, even those that are external, for example using the -l options. However, packages are handled by gpmi, and the linker won't see them, linking will fail.

3. Solution: static packages

A gpmi package is compiled in two versions, a NAME.so for dynamic linking and a NAME-static.o for static linking. The default (and recommended) way is to use dynamic packages - most document assumes you did so. However, you can use static packages as well.

A static package is not loaded runtime, but is linked in the application binary. There is no way to replace a static package while the application is running, on the other hand, the application may access any of the symbols directly.

For applications depending on gpmi packages, it is recommended to use those packages as static packages. It is possible to use static and dynamic packages together (and this is the default).

4. Alternative solutions

Here I list some alternatives, each with different advantages. No example codes for these.

4.1. Function pointers

A relatively clean solution, that doesn't need a wrapper around the whole application, is not to call package routines directly. Instead, have a definitions for all referenced package routines as pointers (pointing to NULL by default). After the application initializes gpmi, it should load the packages it depends on, passing a special routine as the command registration callback. This special routine would load all the function pointers we defined earlier.

However this solution is clear and structured, it has several drawbacks:

This solution still could be usable in a situation where the host application uses only a very small number of package routines.

4.2. Writing modules instead of applications

This is another clean solution. You export all the package-dependent code of your application into a module (or modules). The host application itself doesn't do much more than loading gpmi and these modules. It's still more than the loader of section 4.3, since the application may do all the init/uninit tasks, provide a framework or anything else that does not need packages. This solution is better than 4.1. since this more of the code becomes replaceable, even runtime. However, this forces more of the gpmi design (with RunTick and RunData) on your application's design.

4.3. Using a loader

Before implementing sttaic packages, this was the recommended way. All the code of the application is compiled in a .so file, while a thin wrapper (loader application) is provided which loads the .so file. The only advantage this method has is that the .so file can directly access any symbol in any package without compile-time problems and without static package linking.