Linking IVI-COM and IVI-C Methods and Properties
When IVI-COM items, such as methods, properties, parameters, and enums, are added to the driver hierarchy using the IVI-COM Designer, corresponding items are automatically added to the IVI-C hierarchy. For instance, adding an IVI-COM method automatically adds a corresponding IVI-C function. Since IVI-COM and IVI-C represent data types, repeated capabilities, and other driver characteristics differently, Nimbus must perform various transformations when mapping between IVI-COM and IVI-C. In situations where an IVI-COM item cannot or should not be represented in IVI-C, or vice versa, Nimbus provides a means to implement IVI-COM-only and IVI-C-only items. This topic explains important aspects of managing the relationship between the IVI-COM driver and its associated IVI-C wrapper.
This topic only applies to IVI-COM driver projects that have enabled IVI-C wrapper generation on the IVI-C Page of the Driver Settings Editor.
Every IVI-C function accepts a ViSession as its first parameter. The ViSession parameter identifies the instrument I/O session. Nimbus automatically adds a ViSession parameter to every IVI-C function it associates with an IVI-COM method. Inside the implementation of the IVI-C function, the Nimbus-generated code uses the ViSession parameter to locate the correct IVI-COM driver instance to call. The ViSession parameter cannot be deleted from an IVI-C driver function.
At the raw IDL level, all IVI-COM methods return an HRESULT. The HRESULT return value is used to indicate various failure and success conditions. However, the Nimbus IVI-COM Method Editor allows a return type to be specified for each IVI-COM driver method. This is because many environments, such as C# and VB.NET, transform an IVI-COM HRESULT into an exception or other error mechanism. This allows an [out] parameter to be designated as the method's return value and simplifies the use of the IVI-COM method.
By contrast, IVI-C functions always return a ViStatus result. This means that if an IVI-COM method specifies anything other than Void as its return type, an [out] parameter of the specified type must be added to the corresponding IVI-C function function signature. Nimbus adds such an [out] parameter automatically when needed.
When an IVI-COM method is associated with an IVI-C function, the method return type as well as the data type of each parameter must be mapped to an appropriate IVI-C data type. Similarly, an IVI-COM property type must be mapped to its corresponding IVI-C attribute type. Nimbus performs these transformations automatically when an IVI-COM method or property is created and when parameters are added. Most of these mappings are straightforward and are given in the table below:
IVI-COM Data Type
IVI-C Data Type
ViConstString (for [in] parameters)
ViString, plus a BufferSize parameter (for [out] and [in,out] parameters)
(See discussion below.)
IVI-COM drivers use the SAFEARRAY data type for array parameters. One convenient feature of SAFEARRAYs is that they are self-describing -- the number and type of elements present in the array is maintained within the SAFEARRAY itself. IVI-C drivers, however, use C-style arrays. Since C-style arrays are simply pointers, extra parameters must be used with an IVI-C array to indicate the number of elements present. The IVI specifications prescribe specific naming and ordering conventions for these extra "array size" parameters. Nimbus automatically manages these extra IVI-C parameters as follows:
An [in] parameter of type ViInt32 is added to the IVI-C function and placed just before the IVI-C array parameter. The parameter name is based upon the array parameter name, as follows:
This buffer size parameter is used to indicate how many elements (not bytes) have been allocated in the array by the caller. This helps ensure the function implementation does not try to access more elements than are available.
A C-style array is added to the IVI-C function to represent the SAFEARRAY data itself.
If the SAFEARRAY parameter is an [in,out] parameter, then an [out] parameter of type ViInt32 is added to the IVI-C function and placed just after the IVI-C array parameter. The parameter name is based upon the array parameter name, as follows:
This actual size parameter is used to indicate how many elements (not bytes) were filled in by the function implementation. This indicates to the caller how much of the allocated space, as indicated by the buffer size parameter, was actually used.
IVI-COM drivers use the BSTR data type for string parameters. Similar to the COM SAFEARRAY data type, the BSTR data type has the convenient feature of managing the string length internally. All BSTRs are length-prefixed, so extra parameters are never needed to indicate the number of characters present. IVI-C drivers, on the other hand, use character arrays (arrays of ViChar typedef'd to the ViString data type). When used as input parameters IVI-C strings do not need additional length parameters because the string is NULL-terminated and the length is easily determined by the function implementation. However, when strings are used as [out] parameters in IVI-C drivers, an additional buffer size parameter must be used to indicate to the function implementation how many characters have been allocated by the caller. The IVI specifications prescribe specific naming and ordering conventions for this extra "buffer size" parameter. Nimbus automatically manages this extra IVI-C parameter as follows:
An [in] parameter of type ViInt32 is added to the IVI-C function and placed just before the IVI-C ViString parameter. The parameter name is based upon the ViString parameter name, as follows:
This buffer size parameter is used to indicate how many characters have been allocated in the string by the caller. This helps ensure the function implementation does not try to access more characters than are available.
A ViString parameter is added to the IVI-C function to represent the BSTR data itself.
IVI-COM and IVI-C have a few important differences in the way they represent repeated capabilities. The first difference of note is that IVI-C drivers do not support collection-style repeated capabilities. IVI-COM and IVI-C drivers also use a different set of IVI-defined standard methods and properties to manage the repeated capability instances.
The table below presents the required repeated capability methods and properties for IVI-COM and IVI-C drivers based upon the type of repeated capability. For a discussion of the different types of repeated capabilities see the IVI Backgrounder topic on Repeated Capabilities.
Repeated Capability Style
As the table shows, different methods and properties must be maintained in the IVI-COM and IVI-C hierarchies based upon the type of repeated capability. Nimbus automatically handles each case by creating the appropriate IVI-C functions and attributes and associating them with their IVI-COM counterparts.
The case of collection-style repeated capabilities requires special handling since this type of repeated capability is not supported by IVI-C drivers. Whenever a collection-style repeated capability is added to a driver, Nimbus treats the repeated capability as a parameter-style repeated capability in the IVI-C hierarchy. This means Nimbus automatically creates the <CAPABILITY>_COUNT attribute and the Get<Capability>Name function and associates them with the IVI-COM Count and Name properties.
Collection-style repeated capabilities in an IVI-COM driver are always treated as parameter-style repeated capabilities in the IVI-C hierarchy.
Reading and writing IVI-C attributes involves use of special attribute accessor functions that accept a #define'd constant representing the attribute ID and a value parameter. Because this programming model can be a bit cumbersome to work with in practice, the IVI specifications recommend that commonly used IVI-C attributes also expose a corresponding "getter" and "setter" function. By convention, setter functions often have names that begin with "Configure" and getter functions have names that begin with "Query" (although there is no hard requirement to follow these naming conventions).
Using an IVI-C setter or getter function in place of the attribute itself can simplify programming with the IVI-C driver, as shown in the simple example below:
ViSession vi; /* session initialization omitted for clarity */ /* Use the attribute and attribute accessor to set the sample rate to 1000 */ ViStatus status = IviScope_SetAttributeViReal64(vi, VI_NULL, IVISCOPE_ATTR_HORZ_SAMPLE_RATE, 1000); /* Use the setter function to set the sample rate to 1000 */ status = IviScope_ConfigureSampleRate(vi, 1000);
Nimbus provides built-in support for the creation of IVI-C getter and setter functions and it maintains an association between these functions and the attribute so that they can be automatically implemented by Nimbus.
From Solution Explorer, double-click the IVI-COM node to bring up the IVI-COM Designer.
Select a property from the IVI-COM hierarchy.
Right-click on the property and choose Create IVI-C Getter Function or Create IVI-C Setter Function.
The Create IVI-C Getter Function command will not be available if the property is write-only. Similarly, the Create IVI-C Setter Function command will not appear if the property is read-only. Also, if the getter or setter function already exists, then the corresponding context menu command will not be available.
A property that accepts parameters is known as a parameterized property. While IVI-COM drivers naturally support parameterized properties, there is no notion of a corresponding "parameterized attribute" in IVI-C. Thus, whenever a parameter is first added to an IVI-COM property, Nimbus automatically performs the following steps:
If the IVI-COM property has an associated IVI-C attribute, the IVI-C attribute is deleted from the IVI-C hierarchy.
If the IVI-COM property is read-write or read-only, an IVI-C getter function will be created and associated with the property. The getter function will be named as follows:
If the IVI-COM property is read-write or write-only, an IVI-C setter function will be created and associated with the property. The setter function will be named as follows:
There are some instances where it is not possible or desirable to expose an IVI-COM method in the IVI-C driver. Such an IVI-COM method has no associated IVI-C function and is termed an IVI-COM-only method. Correspondingly, there are occaisions where an IVI-C function serves no useful purpose in the IVI-COM hierarchy. This requires IVI-C functions that have no IVI-COM counterpart -- these are termed IVI-C-only functions.
IVI-COM-only methods and properties are established by deleting the associated IVI-C function or attribute.
From the IVI-COM Designer, select the desired method or property.
For a method, right-click and choose Delete IVI-C Function.
For a property, right-click and choose Delete IVI-C Attribute. If the property also has a getter and/or setter associated with it, then you can select Delete IVI-C Getter Function and/or Delete IVI-C Setter Function to remove those as well.
The Info Panel should display None for the associated IVI-C items.
IVI-C-only functions and attributes are created by simply adding an IVI-C function or attribute directly using the IVI-C Designer. Recall that the IVI-C Designer does not push changes to the IVI-COM hierarchy, so anything created directly from the IVI-C Designer is inherently IVI-C-only.
Whenever an IVI-C-only function or attribute is created, it must be manually implemented in the <prefix>.cpp file within the driver project. See the topic Implementing IVI-C-Only Functions and Attributes for more information.
From the IVI-C Designer, select the desired location within the IVI-C tree view.
Right-click and choose Add Function or Add Attribute.
The Info Panel shows that no IVI-COM method or property is associated with the item.
Download a complete CHM version of this documentation here.