Data Acquisition (DAQ) and Control from Microstar Laboratories

Package Multiple Commands

data acquisition filtering data acquisition software channel architecture enclosures services

Multiple DAPL Commands in a Single Downloadable Module

icon

(View more Software Techniques.)

This brief article describes simple coding techniques to package multiple processing commands together as a single downloadable command module. While there is certainly nothing wrong with downloading custom commands one at a time in separate modules, at times it is helpful to install packaged command sets in one operation.

An example

An example of this is the harmonic analysis commands described in the Power Harmonic Analysis with Resampling article on this site. It contains three closely related processing commands. In fact, they are so closely related that they can share a large portion of their code if they are packaged together.

  1. HARMONICS - Harmonic analysis of one phase signal.
  2. HARMONIC3 - Harmonic analysis of a three phase signal set.
  3. HARMONIC6 - Harmonic analysis of a three phase current and voltage signal set.

Even though much of the code is shared, the commands still need unique entry points, and they perform processing in slightly different sequences. The commands must be separately identified to the DAPL system at the time the module is loaded.

The usual one-command form

The most common situation is that each command is completely independent and in a separate module. Each module includes one special function called ModuleInstall for identifying itself to the DAPL system. That code will look something like this.

extern "C" int __stdcall     HARMONICS(PIB **plib);

extern "C" __declspec(dllexport) int __stdcall
   ModuleInstall(void *hModule)
{
   return (
     CommandInstall(hModule, "HARMONICS", HARMONICS, NULL) );
}

// ... the implementation code follows.

Factoring out the linkage code

While combined identification code can be included with any of the individual commands, it is cleaner from a code maintenance standpoint to place the identification code in a separate code module, and to define the entry point names in a separate header file.

Every source code module will need a declaration for its command entry point functions. Each source code module must also include the Developer's Tookit for DAPL header file DTD.H . Set up an application header file MODHEAD.H that includes these declarations.

// Required Developer's Tookit inclusion
#include   "DTD.H"

// Command entry points for this module
extern "C" {
  int   __stdcall HARMONICS(PIB **plib);
  int   __stdcall HARMONIC3(PIB **plib);
  int   __stdcall HARMONIC6(PIB **plib);
}

// End of MODHEAD.H combined module header file

Factoring out the registration functions

The DAPL system will access the ModuleInstall callback function at the time the module is loaded to "register" the contents of the module with the DAPL system. This function installs commands and then returns a code to indicate whether the installation was successful.

Set up a new code module LINKAGE.CPP for identification and registration code. Include the application header. Also include the special DTDMOD.H that declares the ModuleInstall command and linkage structures to the compiler.

  // Identification module for three processing commands
  //   HARMONICS  -  HARMONIC3  -  HARMONIC6
  #include  "MODHEAD.H"
  #include  "DTDMOD.H"
  ...

Now define a ModuleInstall function. Within this function, invoke CommandInstall for each command contained in the module. These calls specify the name to assign to the command, and the entry point to use to begin command execution. Logically combine the returned results to get a code indicating overall success or failure of the registration operation.

  // Install the three commands
  extern "C" __declspec(dllexport) int __stdcall
    ModuleInstall(void *hModule)
  {
    return
    (
      CommandInstall(hModule, "HARMONICS", HARMONICS, NULL)  &&
      CommandInstall(hModule, "HARMON3", HARMON3, NULL)  &&
      CommandInstall(hModule, "HARMON6", HARMON6, NULL)
    );
  }

  // End of LINKAGE.CPP identification module

Code clean up

The hard work is done. Go back to the original code modules. In each, include the new MODHEAD.H file. Remove lines that include the DTD.H file. Remove the lines that declare command entry point functions. Remove any boilerplate ModuleInstall functions.

Modify the build

In your compiler invocation, you will need to specify that the LINKAGE.CPP is the main module to compile, and that the other code modules are supplementary code files to be compiled and linked in. The new MODHEAD.H file will be a compile dependency for the original code files and also for the new LINKAGE.CPP file.

Conclusions

The usual way of declaring the identification and registration code for a custom command module is actually a simplified special case of the general multiple-command form shown in this note. The minor complication of reorganizing the code is compensated by simpler code for the individual commands. Because of the way the implementations are isolated from the linkage, it is even possible to build the downloadable module from the same compiled commands in more than one way, for example, as an isolated command for testing, then with a group of commands for release. The differences are completely controlled by the configuration in the LINKAGE.CPP file. Choose the way that makes your custom commands easiest to manage and use.

 

Return to the Software Techniques page.