Module Interfaces

The Pandora Engine uses an API system that has been designed for multi-platform development. In this section we'll give you an introduction as to how this system works, and further on in the manual you will be able to learn how to create modules of your own devising. It is also worth keeping in mind that generally we do not use the term 'API', as 'module' is more reflective of the system's modular design, but for the time being you can think of them as one and the same.

Background

The Pandora Engine's module system has been designed to allow code to be shared between programs. It keeps track of how many programs are using a module, and if at some point the open count is reduced to zero, it is possible to 'expunge' the code from memory when resources are running low, or when the developer needs the module code to be re-loaded. Support for version and revision number checking is included, and information on a module's author, revision date and copyright can be stored and retrieved.

Modules are stored within the directory referred to by the 'system:' assignment. Modules are usually given a file extension of '.mod', but depending on the system, they can be compiled with a different extension - for instance Linux based modules have a '.so' extension. The Rocklyte FTP site serves as an official repository for registered modules, so the latest versions of most modules can be picked up from there, as and when they are needed.

Modules are compiled into binary formats that are native to the systems to which they are targeted. For instance, Linux modules are compiled in ELF format, while Windows modules are compiled in DLL format. This means that modules are not portable between systems without a conversion mechanism that supports foreign executable formats. In future, a standard file format for binaries may be adopted to solve this problem.

Finally, modules that are created by developers for the purpose of use within the Pandora community are obliged to register their creation with Rocklyte Systems. This procedure ensures that naming conflicts are avoided, as well as lessening the chances of duplication of effort. Module interfaces are also checked to make sure that they comply with existing standards before they are accepted, which provides an assurance to other developers that the module design does not deviate from accepted practice. The process of registration is free of charge.

Opening a Module

The following code segment illustrates one way of opening the Strings module:

   struct Module      *StringsMod;
   struct StringsBase *StringsBase;

   if (NewPrivateObject(ID_MODULE, NULL, &StringsMod) IS ERR_Okay) {
      SetField(StringsMod, FID_Name, FT_POINTER, "strings");
      if (Action(AC_Init, StringsMod, NULL) IS ERR_Okay) {
         GetField(StringsMod, FID_ModBase, FT_POINTER, &StringsBase);
      }
   }

Although it looks a little complicated for such a simple procedure, the code is extensive because modules are loaded into the system as objects. This makes it easier to get information about the Module and manipulate it after it has been loaded, if you need to. Breaking the routine down, the code first creates a new module object by using the NewPrivateObject() function. It then sets the module to load the Strings file, before initialising the module object to load the code into the system. If successful, the ModBase is grabbed, which contains the addresses required to make function calls to the module. The procedure is then complete, and we can make function calls to the module as we please. Of course, a well written program will terminate its connection with a module when it no longer requires its services. We can free our Strings module using the following code:

   Action(AC_Free, StringsMod, NULL);

Function Calls

Function calls are made to a module through its Module Function Base, or ModBase for short. The ModBase is a structure that contains addresses that refer to all of the functions that a module supports. The following example is a shortened version of the Strings base structure, which comes from the modules/strings.h include file:

   struct StringsBase {
      LONG   (*IntToStr)(LONG, STRING, LONG);
      LONG   (*StrShrink)(STRING, LONG, LONG);
      LONG   (*StrExpand)(STRING, LONG, LONG);
      void   (*StrInsert)(STRING, STRING, LONG);
      LONG   (*StrSearch)(STRING, STRING, WORD);
      ...
   };

If we wanted to call the IntToStr() function, we need to call it using code in the following format:

   StringsBase->IntToStr(100, Buffer, BufferLength);

To simplify API calls, macros are used behind the scenes to make the process of making function calls easier for the developer. Example:

   #define IntToStr(a,b,c) (StringsBase->IntToStr(a,b,c))

Using the above macro, we can convert our code to the following:

   IntToStr(100, Buffer, BufferLength);

As a developer, you don't need to worry about creating your own macros as they are already defined in the include files for each module. To get a list of all the functions that a module supports, you need to refer to its documentation, where you will find details on the supported arguments and an overview of how each individual function operates.

Class Modules

Class modules are treated like function-based modules in every respect, except they create classes as part of their initialisation process. If necessary, a class module may export a set of functions as desired by the developer, but in most cases a class module will create one or two classes for the system, then sit back and wait until the classes are no longer in use before the module is removed.

Unlike function modules, whenever you want to use an external class there is no need for you to load the associated module in advance. The NewObject() function, which is responsible for the creation of all new objects within the system will automatically load the module code for you, relieving you of the complex issue of module management.

For further information on modules, refer to the Module Development Guide, the Class Development Guide, and the documentation for the Module object.

Next: Hello World


Copyright (c) 2000-2001 Rocklyte Systems. All rights reserved. Contact us at feedback@rocklyte.com