Click or drag to resize

Implementing Class-Compliant Interfaces

Class-Compliant Implementation Basics
Note Note

If you are implementing the IviFgen instrument class specification, please see the topic Special Notes on Implementing IviFgen.

Unsupported Methods and Properties

By default, Nimbus generates code that returns an IVI-defined error (E_IVI_METHOD_NOT_SUPPORTED or E_IVI_PROPERTY_NOT_SUPPORTED) indicating that the method or property is not supported. If the driver does not support a particular class-compliant feature, then you may simply leave the auto-generated implementation of the associated method or property as is.

Note Note

If the driver has enabled IVI-C wrapper generation and a class-compliant method or property is not supported, then you must prevent the method or property from being exported in the IVI-C driver by deleting the associated IVI-C function or attribute. See the topic Linking IVI-COM and IVI-C Methods and Properties.

Repeated Capability Interfaces and Interface Reference Properties

repeated capability interfaces are exposed from both the class-compliant and instrument-specific interfaces. Both implementations must expose the same set of repeated capability instances. Nimbus automatically generates a suitable implementation of the Count, Item, and Name properties to accomplish this. There generally is no need to modify the implementation of these properties.

Nimbus also generates a suitable implementation for interface reference properties in class-compliant interfaces. Generally, these property implementations can be left as is.

Leveraging the Instrument-Specific Code

Most IVI-COM drivers are designed such that the full functionality of the instrument is exposed in the instrument-specific interfaces. This means that the functionality in the class-compliant interfaces is necessarily a subset of that in the instrument-specific interfaces. Thus, the best strategy for implementing class-compliant methods and properties is to use the code in the instrument-specific methods and properties. This allows all of the real driver logic to be consolidated in one set of methods and properties.

Delegating a class-compliant method call to an instrument-specific method call is generally a simple matter. There are two specific areas that do require particular attention:

  1. The syntax used to invoke the instrument-specific method or property

  2. Translating IVI-defined enum values to instrument-specific enum values

Syntax for Invoking Instrument-Specific Methods

The proper syntax for invoking an instrument-specific method from a class-compliant method is as follows:

_<interfaceName>::<methodName>(...)

Note that the leading underscore is required in the syntax above. Also, note that the above syntax is required for both instrument-specific and class-compliant methods calls made from any location within the driver code -- not just from within class-compliant code.

The reason it is so important to invoke methods and properties in this way is that the above syntax ensures the method call goes through the Nimbus generated pre-processing and post-processing code in the ForwardingShims.nimbus.cpp file. The code in this file provides a wide variety of important services, such as parameter validation, thread safety, range checking, state caching, and more.

Caution note Caution

Directly calling a driver method or property in any other fashion than that described above completely bypasses important logic.

For more details on the proper syntax for calling methods and properties from within the driver, see the topic Calling Driver Methods and Properties.

The example below demonstrates how to implement the class-compliant IIviRFSigGenFM.Deviation property setter by delegating to the Deviation property setter on the instrument-specific IAcme4321FM interface.

C++
// CoAcme4321.cpp
HRESULT Acme4321::IIviRFSigGenFM_put_Deviation(double Deviation)
{
   HRESULT hr = S_OK;

   hr = _IAcme4321FM::put_Deviation(Deviation);

   return hr;
}

Translating Class-Compliant Enum Values to Instrument-Specific Enum Values

For methods and properties that accept enum parameters, the IVI-defined enum value passed in through the class-compliant method must be translated to the corresponding instrument-specific enum value. In addition, the class-compliant implementation must return a specific IVI-defined error (E_IVI_VALUE_NOT_SUPPORTED) if one of the enum values defined by IVI is not supported by the driver.

The example below demonstrates how to translate IVI-defined enum values before delegating to the instrument-specific method. Note that this particular instrument does not support frequency stepped sweeps or power stepped sweeps, so the implementation returns E_IVI_VALUE_NOT_SUPPORTED if the user attempts to set the mode to frequency step or power step.

C++
// CoAcme4321.cpp
HRESULT Acme4321::IIviRFSigGenSweep_put_Mode(IviRFSigGenSweepModeEnum val)
{
   HRESULT hr = S_OK;

   switch (val)
   {
      case IviRFSigGenSweepModeNode:
         hr = _IAcme4321Sweep::put_SweepMode(Acme4321SweepModeOff);
         break;
      case IviRFSigGenSweepModeFrequencySweep:
         hr = _IAcme4321Sweep::put_SweepMode(Acme4321SweepModeFrequency);
         break;
      case IviRFSigGenSweepModePowerSweep:
         hr = _IAcme4321Sweep::put_SweepMode(Acme4321SweepModePower);
         break;
      case IviRFSigGenSweepModeFrequencyStep:
         hr = ReportError(IDS_E_IVI_VALUE_NOT_SUPPORTED, _T("IviRFSigGenSweepModeFrequencyStep"), _T("val"), _T("put_Mode"));
         break;
      case IviRFSigGenSweepModePowerStep:
         hr = ReportError(IDS_E_IVI_VALUE_NOT_SUPPORTED, _T("IviRFSigGenSweepModePowerStep"), _T("val"), _T("put_Mode"));
         break;
      case IviRFSigGenSweepModeList:
         hr = _IAcme4321Sweep::put_SweepMode(Acme4321SweepModeList);
         break;
   }

   return hr;
}

Translating Instrument-Specific Enum Values to Class-Compliant Enum Values

When a read operation is performed on an enum property, the instrument-specific implementation will return an instrument-specific enum value. There may not be an IVI-defined enum value that maps to the value returned from the instrument-specific property. In this case, IVI requires that the class-compliant implementation return the well-known error E_IVI_UNEXPECTED_RESPONSE.

The example below demonstrates how to map instrument-specific enum values to class-compliant enum values. Note that if the instrument-specific call returns a mode value of Acme4321SweepModeDualSweep, the class-compliant implementation returns the error E_IVI_UNEXPECTED_RESPONSE.

C++
// CoAcme4321.cpp
HRESULT Acme4321::IIviRFSigGenSweep_get_Mode(IviRFSigGenSweepModeEnum* val)
{
   HRESULT hr = S_OK;

   Acme4321SweepModeEnum eMode;
   hr = _IAcme4321Sweep::get_SweepMode(&eMode);
   if (SUCCEEDED(hr))
   {
      switch (val)
      {
         case Acme4321SweepModeOff:
            *val = IviRFSigGenSweepModeNode;
            break;
         case Acme4321SweepModeFrequency:
            *val = IviRFSigGenSweepModeFrequencySweep;
            break;
         case Acme4321SweepModePower:
            *val = IviRFSigGenSweepModePowerSweep;
            break;
         case Acme4321SweepModeDual:
            // IVI does not define a "Dual" sweep type
            hr = ReportError(IDS_E_IVI_UNEXPECTED_RESPONSE);
            break;
         case Acme4321SweepModeList:
            *val = IviRFSigGenSweepModeList;
            break;
         default:
            hr = ReportError(IDS_E_IVI_UNEXPECTED_RESPONSE);
            break;
      }
   }

   return hr;
}
See Also

Download a complete CHM version of this documentation here.