From SmartEiffelWiki

Plugins are a means to augment in a spectactular manner the capabilities of SmartEiffel, by incorporating libraries which have the color, smell, and taste of the standard libraries. In fact, it's an extension of the standard Eiffel mechanism, externals.

The goal of plugins is independence from the back-end. This means that, potentially, the same library could be used simultaneously by compile_to_c and compile_to_jvm. Note that in the future we want to provide other back-ends. In this case, the plugin system will become more important.

Table of contents

How does it work ?

A plugin is made up of two interdependent parts :

  • the Eiffel side, which provides an interface usable by other Eiffel objects ;
  • the external side, which implements the plugin's interface for one or several back-ends (for example, C and Java).

The Eiffel side is 100% Eiffel code, and it uses external features that allow crossing the barrier to the other side of the plugin. The barrier is managed by SmartEiffel : the compiler associates external functions with the external features using configuration files furnished by the plugin.

Eiffel Side

The Eiffel side uses external features. The syntax is as follows:

   my_plugin_feature is
      external "plug_in"
      alias "{
         location: "/path/to/my/plugins"
         module_name: "my_plugin"
         feature_name: "feature"

Of course, a feature can take arguments and return a result ! (after all, it's an external) ;-)

Beware however, it is necessary to only pass and return only basic expanded base types : (INTEGER, BOOLEAN, etc.) or use POINTER (common usage: a_string.to_external).

  • location indicates the directory where you store one or many of your plugins. This path can contain environment variables (either true system environment variables, or variables definined in the [Environment] section of your configuration file).

For example, the standard SmartEiffel libraries are defined by using the following location:

location: "${sys}plugins"
  • module_name contains the plugin name itself. This must be the name of a sub-directory of location that contains a directory for a specific back-end (for example, c for the C generator, java for the Java generator). The content of each of these sub-repositories depends on the generator, and is specified below.
  • feature_name is the name of the feature, function, method etc. named by the back-end (for example, C calls functions, Java calls methods). What they're called is not important : they're all features ;-)

Dark side

C Generation

The C back-end uses a sub-directory of your plugin named c. the files used are:

  • all the .c files, which are included in the compiler-generated C files
  • all the .h files, which are included in the compiler-generated header file
  • the libs file, which contains a description of the native libraries to link
  • the paths file, which contains a description of the paths used to find the libraries
  • the includes file, which contains a description of the paths used to find header files
  • the auto_init file, which contains a description of a possible initialization function called at the very start of the program
  • the file, which is a cecil description automatically taken into account

The .c and .h files are included in alphabetic order.

The includes, libs and paths files use an identical syntax to that of the configuration file, but with different keys:

  • The sections carry the operating system name, the flavor from the configuration file and finally the C compiler used, in that order and separated by a period. If the plugin doesn't depend on one of these elements, it can be omitted.
  • The keys in these files are only informative; however, the values are used to generate command line calls to the C compiler.

The auto_init file uses the same syntax as the configuration file, but with yet other keys:

  • The default section (i.e. the first one, without a name between square brackets) contains one key, function which value gives the name of the initialization function to call at the start of the system
  • Any other section describes plugin dependencies. The must have two keys: location and module_name which have the same meaning as in the Eiffel alias. Those dependencies describe initialization order (initialize dependencies first).

The file is automatically included as it were specified by the -cecil option.

For examples, you can examine the configurations files for Vision or ncurses. There is also a tutorial called mini_gtk (in the SmartEiffel/tutorial/plugin directory).

Note: when there are no arguments, names are generated without parentheses. This permits to attributes, variables and to macros. The absence of parentheses is not then a bug but a desired behavior. In the case where one wants access to a function without an argument, it suffices to use a macro to replace a name without parentheses with the name of the function to call.

Java Generation

For the Java back-end, the plugin sub-directory must be named java. The compiler uses the following files :

  • the .java files are compiled using the command line options and/or from the configuration file (see compile_to_jvm for more detail). The .class files so generated are automatically copied in the compilation directory of the program.
  • the .class files, if they are present and if they are more recent than the corresponding .java files are utilized in place of a compilation of the .java files, in the same manner as the make command under UNIX.

To shorten the compilation time of a program dependent on plugins supplied with the compiler (like for example the io plugin), the installer will compile the .java plugin files during installation.

Other languages