+ All Categories
Home > Documents > [IEEE 2012 IEEE AUTOTESTCON - Anaheim, CA, USA (2012.09.10-2012.09.13)] 2012 IEEE AUTOTESTCON...

[IEEE 2012 IEEE AUTOTESTCON - Anaheim, CA, USA (2012.09.10-2012.09.13)] 2012 IEEE AUTOTESTCON...

Date post: 08-Dec-2016
Category:
Upload: kirk
View: 213 times
Download: 0 times
Share this document with a friend
6
Simplifying Test System Development with IVI.NET Kirk Fertitta Pacific MindWorks San Diego, CA [email protected] Abstract—The IVI Foundation has developed and maintained specifications for building instrument drivers for more than a decade. Until recently, there were two choices for building IVI- compliant instrument drivers – IVI-COM and IVI-C. Each of these driver technologies offers its own advantages for specific types of users, and each comes with its own set of disadvantages. The release of the IVI.NET specifications from the IVI Foundation introduces a new mechanism for controlling instrumentation from test system software. As a great deal of Windows desktop application development (as well as a considerable amount of web development) has shifted to the Microsoft .NET platform, the demand for tools that help test system developers work with .NET has grown. Conventional desktop application developers have benefited considerably from the productivity gains of working with .NET, and test system developers have already begun to enjoy the same. Having a driver technology that fully capitalizes on the benefits of the .NET platform and that marries naturally with .NET-based test system software is critical. This paper will examine the new IVI.NET standard and take a practical look at how IVI.NET drivers can simplify test system development. I. FLAVORS OF IVI DRIVERS IVI drivers have become prevalent in the test and measurement market over the past decade. During that period, two kinds of IVI drivers emerged – IVI-C and IVI-COM. IVI- C drivers evolved from the VXI Plug-n-Play standard and are simple dynamic linked libraries with standardized entry points. IVI-COM drivers arose out of a need to supply a single driver that could work well in a wide variety of application development environments (ADEs). IVI-COM drivers leverage Microsoft’s COM technology for which nearly all important ADEs provided some level of integrated support. An instrument manufacturer could author their IVI-COM driver in C++ and provide a first-class experience for end users working in ADEs as disparate as Visual Basic, C#, C++, LabVIEW, or even Microsoft Excel. With the release of the Microsoft .NET platform, end users needed a mechanism for easily accessing IVI drivers from .NET applications, such as those written in C# or Visual Basic.NET. Given the immense install base of COM components on the Windows platform, it was not surprising that Microsoft itself had introduced with the .NET platform a means for accessing native COM components from .NET applications. This technology, known as COM interop, is what IVI drivers rely upon for supporting .NET applications. The IVI Foundation went one step further in creating standardized interop assemblies (known as primary interop assemblies) that provide for interchangeability between IVI-COM drivers being used in .NET applications. For years, the scheme of IVI-COM driver access via .NET interop has served test application developers quite well. IVI uses the same core, robust functionality baked into the .NET platform that the rest of the world relies upon. As .NET matured, it became clear that most customers using IVI-COM drivers were doing so via .NET applications. Fewer and fewer customers were expressing a need for IVI-COM access from native C or C++ applications at all. Programmers working in C or C++ often turned to IVI-C drivers. Though COM interop works well, there are conspicuous disadvantages, and IVI- COM drivers themselves are internally quite complex. The need for a pure .NET driver that catered specifically to .NET- based end users became clear, and the resulting IVI.NET standards were the IVI Foundation’s answer to this need. II. SIMPLIFIED DRIVER SOURCE Arguably the most compelling motivation for IVI.NET drivers is that the source code is much simpler than IVI-COM or IVI-C driver source code. In the case of IVI-COM, even a simple driver with minimal functionality requires a multitude of source files and special tools to implement the necessary COM plumbing. Many driver developers are unfamiliar with COM programming, as are many end users building applications with IVI drivers. In addition to COM itself, the C++ programming language, which is typically used to build IVI-COM drivers, presents its own set of challenges to many test and measurement professionals. Many developers have found the programming model for .NET to be far simpler than COM or C or C++. Simpler source code has several implications for driver developers and for end users building applications with IVI drivers. First, simpler source code means that IVI.NET drivers themselves are easier to develop than either IVI-COM or IVI-C drivers. If the drivers are easier to develop, then instrument vendors will be 978-1-4673-0700-0/12/$31.00 ©2012 IEEE
Transcript

Simplifying Test System Development with IVI.NET

Kirk Fertitta Pacific MindWorks

San Diego, CA [email protected]

Abstract—The IVI Foundation has developed and maintained specifications for building instrument drivers for more than a decade. Until recently, there were two choices for building IVI-compliant instrument drivers – IVI-COM and IVI-C. Each of these driver technologies offers its own advantages for specific types of users, and each comes with its own set of disadvantages. The release of the IVI.NET specifications from the IVI Foundation introduces a new mechanism for controlling instrumentation from test system software. As a great deal of Windows desktop application development (as well as a considerable amount of web development) has shifted to the Microsoft .NET platform, the demand for tools that help test system developers work with .NET has grown. Conventional desktop application developers have benefited considerably from the productivity gains of working with .NET, and test system developers have already begun to enjoy the same. Having a driver technology that fully capitalizes on the benefits of the .NET platform and that marries naturally with .NET-based test system software is critical. This paper will examine the new IVI.NET standard and take a practical look at how IVI.NET drivers can simplify test system development.

I. FLAVORS OF IVI DRIVERS IVI drivers have become prevalent in the test and

measurement market over the past decade. During that period, two kinds of IVI drivers emerged – IVI-C and IVI-COM. IVI-C drivers evolved from the VXI Plug-n-Play standard and are simple dynamic linked libraries with standardized entry points. IVI-COM drivers arose out of a need to supply a single driver that could work well in a wide variety of application development environments (ADEs). IVI-COM drivers leverage Microsoft’s COM technology for which nearly all important ADEs provided some level of integrated support. An instrument manufacturer could author their IVI-COM driver in C++ and provide a first-class experience for end users working in ADEs as disparate as Visual Basic, C#, C++, LabVIEW, or even Microsoft Excel.

With the release of the Microsoft .NET platform, end users needed a mechanism for easily accessing IVI drivers from .NET applications, such as those written in C# or Visual Basic.NET. Given the immense install base of COM components on the Windows platform, it was not surprising

that Microsoft itself had introduced with the .NET platform a means for accessing native COM components from .NET applications. This technology, known as COM interop, is what IVI drivers rely upon for supporting .NET applications. The IVI Foundation went one step further in creating standardized interop assemblies (known as primary interop assemblies) that provide for interchangeability between IVI-COM drivers being used in .NET applications.

For years, the scheme of IVI-COM driver access via .NET interop has served test application developers quite well. IVI uses the same core, robust functionality baked into the .NET platform that the rest of the world relies upon. As .NET matured, it became clear that most customers using IVI-COM drivers were doing so via .NET applications. Fewer and fewer customers were expressing a need for IVI-COM access from native C or C++ applications at all. Programmers working in C or C++ often turned to IVI-C drivers. Though COM interop works well, there are conspicuous disadvantages, and IVI-COM drivers themselves are internally quite complex. The need for a pure .NET driver that catered specifically to .NET-based end users became clear, and the resulting IVI.NET standards were the IVI Foundation’s answer to this need.

II. SIMPLIFIED DRIVER SOURCE Arguably the most compelling motivation for IVI.NET

drivers is that the source code is much simpler than IVI-COM or IVI-C driver source code. In the case of IVI-COM, even a simple driver with minimal functionality requires a multitude of source files and special tools to implement the necessary COM plumbing. Many driver developers are unfamiliar with COM programming, as are many end users building applications with IVI drivers. In addition to COM itself, the C++ programming language, which is typically used to build IVI-COM drivers, presents its own set of challenges to many test and measurement professionals.

Many developers have found the programming model for .NET to be far simpler than COM or C or C++. Simpler source code has several implications for driver developers and for end users building applications with IVI drivers. First, simpler source code means that IVI.NET drivers themselves are easier to develop than either IVI-COM or IVI-C drivers. If the drivers are easier to develop, then instrument vendors will be

978-1-4673-0700-0/12/$31.00 ©2012 IEEE

able to supply more drivers for a broader array of instrumentation. More time will be available to invest in making the drivers complete and to invest in driver testing. This benefits the instrument vendor and all of the end user companies seeking to build .NET-based applications.

Simpler source code for IVI.NET also means better source code availability for end users. Many vendors have made the source code available for their IVI-COM and IVI-C drivers for years. End users rely on driver source code for a variety of purposes. Some use the driver source code as a learning tool for understanding how to program the instrument directly (without an IVI driver). Other users simply want to understand at a deeper level how the driver works. They may need to modify the driver to fix a bug quickly. Still other users would like to extend the functionality of the driver to include missing features or to capitalize on functionality in a newer version of the firmware than was available when the driver was authored.

From a practical perspective, few of the above goals of driver source code availability were served by many existing IVI drivers. With IVI.NET, driver source code is infinitely simpler. Users can easily debug directly from their .NET application into the IVI.NET driver source code. Modifying a driver and recompiling it to address a bug or feature issue will feel just as natural as the .NET coding they already do in their client application.

III. TOOLING FOR IVI.NET

A. Refactoring Driver Code With nearly all software standards, the availability of

quality tooling often plays a key role in the success of that standard. With IVI drivers, quality driver development tools are a crucial enabler for instrument vendors seeking to outfit their product catalogs with IVI drivers. Useful driver development tools, such as Nimbus Driver Studio from Pacific MindWorks and LabWindows/CVI from National Instruments, have been available for years. These tools provide good support for creating IVI-COM and IVI-C drivers. However, these tools are ultimately limited in the amount of automated code management they can perform due to the inherent complexities of the C/C++ language family. The C++ language, in particular, is quite complex – both syntactically and semantically. In order to facilitate driver development, tools need to understand the basic structure of driver source code. This enables the tool to automatically offer features such as automated driver designers that present a graphical user interface (GUI) to the driver developer and automatically translate GUI operations into textual code edits. This is often referred to as code roundtripping or code refactoring.

Refactoring C++ code is extraordinarily difficult. The inherent complexities of the language syntax account for a great deal of this complexity. Dealing with just two C/C++ language features alone creates immense complexities for tools – processing header files and expanding macros. It is no coincidence that neither header files nor macros are available in .NET languages such as C# or VB.NET – indeed, there is no preprocessor at all. Advanced C# and VB.NET refactoring tools have been available in Visual Studio for years; yet, even

in the latest version of Visual Studio, support for refactoring C++ code is virtually non-existent.

The ability to create more advanced tooling for IVI.NET is already evidenced in some commercially available products, such as Nimbus Driver Studio. The code below shows the implementation of a Configure method in a Nimbus-created IVI.NET driver.

[DriverMethod] public void Configure() { if (this.InstrumentIsModel(Models.ModelA)) { this.IO.FormattedIO.PrintfAndFlush(“CONFIG:AAA”); } else if (this.InstrumentIsModel(Models.ModelB)) { this.IO.FormattedIO.PrintfAndFlush(“CONFIG:BBB”); } else { this.IO.FormattedIO.PrintfAndFlush(“CONFIG”); } }

The above code sends the appropriate command to the

device based upon which instrument model is in use. Nimbus internally manages a code model of each IVI.NET driver method and property. This model includes a full syntactic and semantic model of driver method declarations and internal implementation code. With this model, Nimbus has the ability to roundtrip code within a method body. In the above Configure method, Nimbus can automatically update the method body when the Nimbus user modifies a setting in the graphical driver designer. For instance, the Nimbus user has a designer for defining the instrument command to send for a particular instrument model. When the user operates in the GUI, Nimbus locates the appropriate parameter within the Configure method’s if-else structure and updates it accordingly. Similarly, if an instrument model is renamed, then the parameter to the InstrumentIsModel method is automatically updated – and that update is performed not only within the Configure method, but within all methods in the entire driver where the renamed model is referenced. If additional model-specific commands are defined or removed, then the appropriate if-else clauses are added to or removed from the method implementation. It is important to note that this refactoring is done using a full semantic model of the code – it is not done with simple text or regular expression-based pattern matching. So, introducing things such as code comments does not impact the ability to roundtrip driver code.

B. Static Analysis The code model used by Nimbus to refactor code is also

leveraged to perform static analysis. Static analysis has become a popular feature with .NET programmers working in Visual Studio. Built-in static analysis rules allow Visual Studio to highlight common coding errors. Nimbus extends this capability by defining custom static analysis rules tailored to IVI.NET driver developers and end users. A complete discussion of these rules is beyond the scope of this paper, but a simple, but important, example can be found by examining

the Printf function used to perform instrument I/O in IVI.NET drivers. This function is quite analogous to the C-runtime library’s printf function. The code below shows how an IVI.NET driver might invoke the Printf function to send a formatted command to an instrument. [DriverMethod] public void Configure(double bandwidth, double frequency) { // ... io.Printf(“CONFIG %g,%g,%s”, bandwidth, frequency); }

The code above has a serious bug – the number of ‘%’

format specifications (3) does not match the number of parameters supplied (2). This is a very common bug in C/C++ programs as well – and the consequences in those programs can be much more severe, as memory corruption typically results. This is a commonly exploited security vulnerability in C/C++ programs. In .NET applications, a runtime exception will be thrown. But, with custom static analysis rules, Nimbus is able to interrogate all calls to the Printf function and detect and report the error at compile time.

Consider the following version of the Configure method.

[DriverMethod] public void Configure(double bandwidth, double frequency) { // ... io.Printf(“CONFIG %g,%s”, bandwidth, frequency); }

This version also has a bug in the usage of Printf – the

%s format specification calls for a string parameter as the 2nd parameter to the Printf call, but the frequency parameter (of type double) has been supplied. With its full semantic code model, Nimbus is able to determine that the 2nd parameter is of the wrong type and the error is reported at compile time.

C. Driver Metadata and Reflection Many, if not most, of the unique features of the .NET

platform can be traced to the much richer metadata baked into .NET components. .NET components are much more self-describing than compiled native code. This allows tools of all sorts, such as browsers, to easily interrogate an IVI.NET driver and understand much more about the features it offers, the dependencies it has, some specifics about how it may be implemented and more. The standard .NET reflection library is a commonly used API for accessing .NET component metadata. Other more advanced metadata APIs are also available. And, all of the .NET metadata is consolidated in a single location – the .NET assembly itself. By comparison, the metadata available from IVI-COM and IVI-C components is quite limited. It is also much more disparate. IVI-COM metadata is spread between the driver type library, the registry, and the IVI Configuration Store, and, potentially, in other places.

IV. RICHER TYPE SYSTEM

A. Limits of IVI-COM and IVI-C Data Types Both IVI-COM and IVI-C drivers suffer from a somewhat

limited set of data types that can be exposed to the client application. IVI-COM and IVI-C drivers can expose primitive types, such as integers, floats, Booleans, and strings, as well as arrays of those primitive types. The type system for IVI-COM is imposed by what is known as the OLE automation type system – a subset of C++ data types that ADEs must understand in order to be automation-compliant. Limiting IVI-COM drivers to this automation subset was an explicit decision made by the IVI Foundation to ensure IVI-COM drivers would work in the broadest possible set of ADEs. At the time the IVI-COM specifications were under development, Visual Basic 6 was the most important COM ADE and it required automation compliance. (In truth, the Visual Basic team at Microsoft actually defined the automation type system.)

IVI-C drivers have an even more limited type system which becomes evident in very common scenarios. For instance, simple arrays of strings are not supported in IVI-C. Instead, IVI-C drivers often expose a comma-separated list of strings – thereby requiring the client programmer to parse the list into its constituent string elements. Arrays in general are a bit cumbersome in IVI-C because extra parameters must be used to communicate the number of elements in the array. Consider the following function from the IviScope specification.

IviScope_FetchWaveform(ViSession vi, ViConstString channel, ViInt32 waveformSize, ViReal64 waveform[], ViInt32 *actualPoints, ViReal64 *initialX, ViReal64 *xIncrement); In the above function declaration, the waveformSize,

waveform, and actualPoints parameters are all needed to supply the waveform data points. The waveformSize parameter is an input parameter that specifies the number of array elements allocated by the caller in the waveform buffer. The actualPoints parameter is an output parameter that indicates the number of data points that the callee (the driver) actually fetches and places in the waveform buffer. There is nothing in the C programming language to enforce these semantics, so users and driver implementers must take special care to follow this regimen or serious program errors (including memory-based security vulnerabilities) will result. By contrast, IVI.NET drivers use the standard .NET array data type, which is fully self-describing. Only a single parameter is needed in .NET to accomplish what requires three parameters in IVI-C.

The lack of support for simple structs in IVI-C is also a conspicuous shortcoming in driver APIs. Structs can be supported by IVI-COM drivers by using interfaces, but the technique requires a fair bit of care on the part of the driver implementer and it has proven to be problematic in some COM ADEs. Nevertheless, the need for simple struct support in driver APIs is a very common one. Turning again to the FetchWaveform function declaration above, we see that the initialX parameter and the xIncrement parameter are both

part of the overall waveform description. Indeed, all five parameters after the channel parameter would ideally be part of a single struct parameter. In IVI.NET, such an API element can, in fact, be expressed as a single parameter (an interface, class, or struct). Consider a driver API that required a collection of waveforms – such as in reading multiple waveforms from a digitizer or in downloading complex waveforms to an arbitrary waveform generator. Such a requirement could not be practically met in IVI-C by simply modifying the FetchWaveform function; rather, a set of functions would be needed to manage the data for these multi-waveform APIs. By contrast, in IVI.NET, an array of waveforms can be expressed as just that – an array of waveform structs (or interfaces or classes).

B. Shared IVI.NET Data Types With such a broad array of data types available to IVI.NET

API designers, the IVI Foundation felt it would be useful to offer commonly used IVI.NET data types as part of the IVI.NET Shared Components. The goal of these shared components is two-fold – to increase consistency amongst IVI.NET drivers and to facilitate data interchange between drivers.

For example, many kinds of drivers have a need for a waveform data type. Digitizers and scopes and spectrum analyzers read waveforms, while function generators and RF signal generators serve as waveform sources. In real-world systems, the client application may have a need to read waveform data from a digitizer, process it in some fashion, and pass the result to a source device. Without a common waveform data type, the client programmer would be left with the task of translating waveform data from one kind of driver into any of the possible formats accepted by several other kinds of drivers.

To address this need, the IVI.NET Shared Components include the IWaveform interface. This interface was designed to accommodate the most commonly needed elements of waveform data. A variety of instrument experts involved in the definition of other IVI instruments classes composed the IWaveform definition. In addition to the interface definition, the IVI.NET Shared Components include a complete concrete implementation of the IWaveform interface – the Waveform class. For driver implementers that need only basic waveform semantics, the Waveform class can be used as-is in the driver implementation. For more complex waveform semantics, driver developers are free to introduce their own concrete implementation of IWaveform. In either case, client programmers need only contend with a single, common IWaveform definition to perform many tasks. Since many devices natively operate on data in the frequency domain, the IVI.NET Shared Components even include an ISpectrum interface with a complete concrete implementation available in the Spectrum class.

It is also very common for driver APIs to include time-based parameters, such as timeout values for I/O operations, measurement start and stop times, or timer intervals between data point readings. With IVI-COM and IVI-C drivers, time values are typically represented by integers or doubles. This makes the API less expressive and leaves more than a bit of ambiguity into what the value represents. Is it an absolute time

or an interval? Is the interval seconds or milliseconds or something else? Is the absolute time UTC or something else?

The .NET framework includes specialized data types for dealing with time – the DateTime and TimeSpan data types. These data types offer a clear distinction between absolute time and time intervals. They also offer convenient methods for performing basic math operations on time values. Instruments sometimes require time values that exceed the resolution of the .NET framework DateTime and TimeSpan data types. To address these cases, the IVI.NET Shared Components include the PrecisionDateTime and PrecisionTimeSpan classes. These classes allow representation of time to a precision appropriate for devices that support the IEEE 1588 Precision Time Protocol (PTP).

In addition to waveform handling data types and time-based data types, the IVI.NET Shared Components include a variety of other useful types. Common exceptions classes allow client programmers to more precisely interrogate the source of program errors. There is a common type for representing trigger sources, which makes it convenient to “stitch” together multiple devices in triggered source/measure operations. Importantly, there are also types to assist in implementing thread-based locking consistently and correctly in IVI.NET drivers. This frees the driver developer from many of the pitfalls in multi-threaded .NET programming and offers the end user some degree of assurance in the consistency of IVI.NET driver behavior in multi-threaded environments.

V. SIMPLIFIED USAGE SYNTAX IVI.NET drivers offer a number of syntactic improvements

that make authoring .NET client programs easier than with IVI-COM drivers that rely upon .NET interop assemblies. This section will look at only a few of these syntactic improvements that users frequently encounter.

A. Simplified Access to Repeated Capabilities IVI defines the notion of a repeated capability to represent

devices that exposes sets of functionality, such as channels on an oscilloscope. The most common mechanism for exposing these repeated capabilities from IVI-COM drivers is by using a special kind of parameterized property called the “Item” property. However, in C#, properties cannot have parameters, so the signature of methods that access repeated capabilities gets a bit muddled. The C# code below demonstrates how a C# client would access a particular channel on an IVI-COM driver that implements the IviDCPwr instrument class.

IIviDCPwr dc = new AcmeDCPwrClass(); // … dc.Outputs.get_Item(“Channel1”).CurrentLimit =

3.0 In IVI.NET, repeated capabilities use the standard .NET

indexer mechanism, which allows APIs to expose methods and properties that can be accessed using array-like syntax. The C# code to access a particular channel on an IVI.NET driver would look like the following:

IIviDCPwr dc = new AcmeDCPwr (…); dc.Outputs[“Channel1”].CurrentLimit = 3.0

B. Simplified Access to Enums The syntax for accessing enums in IVI.NET drivers is also

quite a bit simpler than for accessing enums in IVI-COM drivers via COM interop. In IVI-COM, enums and enum members must all have names that are globally unique across all drivers. Thus, IVI requires that IVI-COM enums and enum members be prefixed with the driver name. The following shows how an IVI-COM enum is defined:

typedef enum Acme4301TriggerSourceEnum {

Acme4301TriggerSourceInternal, Acme4301TriggerSourceExternal, Acme4301TriggerSourceSoftware,

} Acme4301TriggerSourceEnum; A C# client program that uses an IVI-COM driver to set a

property that uses this enum would look something like the following:

IAcme4301 driver = new Acme4301Class(); // … driver.Trigger.Source = Acme4301TriggerSourceEnum.Acme4301TriggerSou

rceInternal; In contrast, IVI.NET enumerations are scoped by their

parent namespace and enum members are scoped by their parent enum. This means that neither the enum name nor the enum member names need to be prefixed by the driver name. In real-world programs, this can lead to considerably simpler looking code. The above operation using an IVI.NET driver would look like the following:

IAcme4301 driver = new Acme4301 (…); // … driver.Trigger.Source = TriggerSource.Internal;

C. Clearer Parameter Semantics Programming with drivers of any sort can be complicated

by the need to understand the directional semantics of function parameters. Parameters may be input-only parameters where the driver does not modify the value; they may be output-only parameters where the value on input is ignored and overwritten by the driver; or they may be input-output parameters which may contain valid data on input and output. With IVI-C drivers, there is no syntax or language feature to express or enforce the directional semantics of parameters. Only by referencing documentation can the client programmer know how to treat function parameters. With IVI-COM drivers, there is a way to annotate parameters as being [in]-only, [out]-only or [in/out] parameters. Unfortunately, a peculiar, but well-known, bug in the Visual Basic runtime precludes the use of [out]-only parameters. So, IVI-COM drivers must (somewhat

deceptively) annotate output-only parameters as [in/out]. Consequently, there is no way to distinguish between parameters that really are [in/out] from those that really are [out]-only. This becomes more evident when the IVI-COM driver is accessed from C# because the [in/out] annotation causes the C# ref keyword to appear in the C# signature of the driver method instead of the more appropriate C# out keyword, which indicates output-only parameter semantics. When the ref keyword is used, the compiler forces the user to initialize the parameter before calling the driver method, which is awkward when the parameter really is an output-only parameters. Consider the following IVI-COM method being called from C#.

double[] times; double[] values; driver.Acquisition.Fetch(ref times, ref values); In the above example, the C# compiler will complain that

the local variables times and values are being used without having been initialized. Such initialization should really be unnecessary because the times and values parameters are logically outputs. However IVI-COM cannot support output-only parameters, so the user is forced to modify the code so that the local variables are initialized.

double[] times = new double[0]; double[] values = new double[0]; driver.Acquisition.Fetch(ref times, ref values); With IVI.NET drivers, parameters can properly be marked

as input-output or output-only to accurately represent the semantics of the method. The above method call for an IVI.NET driver would look like the following.

double[] times; double[] values; driver.Acquisition.Fetch(out times, out values); It should be noted that the lack of support for output-only

parameters in IVI-COM drivers can manifest itself in ways other than syntactic oddities. In remoting scenarios where the COM runtime is involved in marshaling data between threads or processes, the use of the [in/out] annotation will cause the COM marshaller to unnecessarily marshal data in both directions – when the method is called and when the method returns. This two-way data marshaling also occurs in the .NET interop layer – between the .NET runtime and the native IVI-COM driver implementation. The severity of this performance hit depends upon the nature of the parameter data, but it always exists to some degree with IVI-COM drivers that have output parameters. With IVI.NET drivers, this unnecessary overhead is completely eliminated.

VI. ERROR HANDLING IVI.NET drivers offer considerable advantages over both

IVI-COM and IVI-C drivers in the area of error handling. IVI-C drivers rely solely on return codes to communicate errors and warnings. The primary disadvantage of this approach is that errors can easily be ignored in the client application. Secondly,

once the error code is retrieved from the IVI-C driver, a second function call is required to retrieve the error message. In the case of IVI-COM drivers, the mode of error handling actually depends upon the client environment. Raw C++ clients will rely on return codes similar to IVI-C drivers. Certain kinds of C++ clients will use special wrapper classes that synthesize exceptions from COM HRESULTs, thereby introducing a particular kind of error discipline for a specific kind of client. For users working with IVI-COM drivers in .NET applications, errors will be manifest as instances of the COMException class. These different mechanisms introduce plenty of opportunity for confusion for both driver developers and driver users.

For errors that may occur deep in the call stack, such as in a low-level operating system call, the way errors are reported depends very heavily on how the driver developer code is written. A file I/O error that occurs inside the driver may present itself to the client programmer in a way that has little apparent relationship to the actual underlying cause of the error.

The .NET exception mechanism used by IVI.NET drivers is far simpler and more effective than that available in IVI-COM or IVI-C drivers. Unlike return codes, exceptions cannot be ignored. Exceptions coming from system calls work the same as exceptions thrown by the driver itself. Users can always see the full context of the error without making any additional function calls and .NET exceptions include a great deal of diagnostic information, such as the stack trace that leads to the original source of the exception. Drivers can handle exceptions internally and add more diagnostic information for the user without losing any information about the exception thrown at the original source.

IVI.NET drivers also support warnings via the standard .NET event mechanism. In IVI-C, warnings are simply error

codes that fall into a different numeric range. In IVI-COM, the distinction between errors and warnings is similar in that it involves a variance of numeric error code values, but the consequences of this variance are much more insidious in IVI-COM. Recall that a failure HRESULT returned from an IVI-COM driver is translated by the .NET runtime into a COMException. However, a warning HRESULT is not translated into an exception. Since the HRESULT return value is removed from IVI-COM methods when creating interop assemblies, this means there is no way for .NET clients to retrieve warnings from IVI-COM drivers. Warnings in IVI-COM drivers are effectively invisible to .NET clients. IVI.NET drivers solve this problem by using .NET events, which allows users to register and handle warnings as they see fit – treating them as critical errors in some situations or ignoring them altogether in other situations.

VII. CONCLUSION This paper has presented several important aspects of the

IVI.NET driver standard and explained a number of important benefits IVI.NET drivers offer over previous driver standards. Simplified driver source code promises a greatly simplified driver development experience and a new level of source code accessibility for end users. Richer data types allow the creation of driver APIs that are more expressive and easier to use. Vastly simpler language syntax and semantics enable the creation of more advanced developer tools that will benefit driver developers and end users alike. As more test and measurement engineers seek to capitalize on the productivity gains of the .NET platform, IVI.NET drivers stand to play an important role in test system development.


Recommended