Creating a Program
[User Manual]

Writing a Program

The Rulbus Device Class Library consists of one or more classes for each Rulbus module. These classes are published in C++ header files, one for each Rulbus module, for example rb8510_dac12.h. You normally need to only call methods for the Rulbus modules you want to use (but also see Handling Errors).

Rulbus modules are used according to the pattern: create -- use -- destroy, for example:

#include "rdcl/rb8510_dac12.h"

int main()
{
   Rulbus::RB8510_Dac12 dac( "mydac", ... );    // create device

   dac.setVoltage( ... );                       // use it
   ...                                          //    even more

   //
   // dac goes out of scope here; it is destroyed automatically
   //
}

Note that the classes reside in the namespace Rulbus.

Besides the Rulbus module related classes, there are general Rulbus device methods. The latter are part of class RulbusDevice. Class names appear in the following forms:

Another way to create and use Rulbus devices is presented in Support for the Rulbus Device Library (DLL).

Compiling the Program

In the following command, {include-path} specifies the directory with the header files and {library-path} specifies the directory with rulbusdcl-omf-static.lib and winutils-omf-static.lib.

To create the program, compile as follows:

C:\>bcc32 -tWM -I(include-path) -L{library-path} {program}.cpp  \
               rulbusdcl-omf-static.lib winutils-omf-static.lib

Option -tWM specifies that the program must be linked with the multi-threaded C runtime library.

Handling Errors

All classes in the Rulbus Device Class Library use the same error handling pattern: they throw an exception when something is not in order. Exceptions may be divided into:

  1. environmental or usage related errors, for example RulbusOpenError
  2. programming or design-by-contract errors, for example RequireException
  3. system errors, for example bad_alloc exception for out-of-memory

A properly written program should always catch the exceptions that may arise to see if the method calls where successful and it should act accordingly. Failing to do so may crudely abort the program giving an "Abnormal program termination" message.

When an error occurred, a string explaining the error condition may be obtained from the exception with method what(). The exception can also be printed on a stream as in the following example.

#include <iostream>             // for std::cerr
#include "rdcl/rb8510_dac12.h"  // for class RB8510_Dac12

int main()
{
   try
   {
      /*
       * create a dac at an invalid Rulbus address (0x123),
       * an environmental error:
       */

      Rulbus::RB8510_Dac12 dac( "mydac", 0x123, 7 );

      // ...
   }
   catch ( const std::exception& e )
   {
      std::cerr << e;
   }
}

The program gives:

Rulbus: cannot open rulbus device 'mydac' at [7:0x123]

For more information on design-by-contract, see [DBC]

Typenames

Several fundamental types and std namespace classes and all classes of this library are made available with standardized names for (const) pointer types and (const) reference types.

typedef       type   Type;
typedef       type*  TypePtr;
typedef const type*  TypeCptr;
typedef       type&  TypeRef;
typedef const type&  TypeCref;

The following compiler dependent types are defined:

int8, uInt8
int16, uInt16
int32, uInt32
float32, float64

The following fundamental library types are defined:

DECLARE_TYPE( uInt8  , Byte   );
DECLARE_TYPE( uInt16 , Word   );
DECLARE_TYPE( uInt32 , Quad   );

DECLARE_TYPE( char   , Char   );
DECLARE_TYPE( int    , Int    );
DECLARE_TYPE( int16  , Int16  );
DECLARE_TYPE( int32  , Int32  );
DECLARE_TYPE( double , Real   );
DECLARE_TYPE( float32, Real32 );
DECLARE_TYPE( float64, Real64 );

The following convenience types are defined:

DECLARE_TYPE( std::string   , String );
DECLARE_TYPE( std::exception, StdException );

For each class 'myClass', the following types are defined via macro DECLARE_CLASS():

class myClass;
typedef       myClass* myClassPtr;
typedef const myClass* myClassCptr;
typedef       myClass& myClassRef;
typedef const myClass& myClassCref;

Complete Example

The following example program creates (opens) a DAC, generates a staircase voltage and destroys (closes) the DAC again.

/*
 * dac.cpp - generate a staircase voltage.
 *
 * Compile: bcc32 -tWM dac.cpp rulbusdcl-omf-static.lib winutils-omf-static.lib
 */

#include <iostream>             // for std::cout etc.
#include <cstdlib>              // for std::strtol()
#include <windows.h>            // for Sleep()
#include "rdcl/rb8510_dac12.h"  // header

static int usage();             // print program usage, return EXIT_FAILURE

/*
 * main - handle commandline arguments and generate staircase voltage on DAC.
 */

int main( int argc, char *argv[] )
{
   try
   {
      /*
       * handle commandline arguments:
       */

      if ( argc < 4 )
         return usage();

      /*
       * for rack and Rulbus address, let strtol() determine the radix of the input:
       *   octal for 012, decimal for 12, hexadecimal for 0x12.
       */

      char *name = argv[1];
      int   rack = std::strtol( argv[2], 0, 0 );
      int   addr = std::strtol( argv[3], 0, 0 );

      const int   bipolar = 1;                // bipolar
      const float vpb     = 5e-3;             // volt-per-bit

      /*
       * create the DAC:
       */

      Rulbus::RB8510_Dac12 dac( name, addr, rack, bipolar, vpb );

      /*
       * generate 11 one volt steps, one per second:
       *
       * Note that the last step generates a RulbusRangeError, because the
       * voltage is outside [-10.235 .. +10.24 V].
       */

      for ( int i = 0; i <= 11; i++ )
      {
         std::cout << '[' << i << ']';

         dac.setVoltage( i );

         Sleep( 1000 );                    // delay one second
      }

      /*
       * dac goes out of scope and is destroyed:
       */
   }
   catch ( const std::exception& e )
   {
      std::cout << std::endl << e << std::endl;
   }

   return EXIT_SUCCESS;
}

/*
 * usage - print program usage.
 */

static int usage()
{
   std::cout << "Usage: dac device-name rulbus-rack rulbus-address" << std::endl;
   return EXIT_FAILURE;
}

previous top next


Generated on Tue Oct 12 14:12:01 2004 for Rulbus Device Class Library for Microsoft Windows by doxygen 1.3.4