Due to the highly transparent integration of the Component Object Model (COM) into the Visual Basic (VB) development environment, VB developers are effectively programming and deploying COM applications today. Unlike their C/C++ counterparts, VB programmers build on concepts that they already know. There are no extra tools, such as the Microsoft Interface Definition Language (MIDL) compiler. Plus, there's no need to initialize the COM system or be aware of the COM runtime's existence because that's all simply integrated into the environment.
COM development is a natural fit for the test and measurement domain, as well as for many other embedded-system applications. Interfaces can be made in VB that correspond to the Standard Commands for Programmable instruments (SCPI) hierarchies. These de-fined interfaces combined with VB's development environment In-telliSense capability essentially eliminate the need for programming manuals.
Still, the value proposition of COM doesn't stop there. For instance, COM offers location independence. A COM object client doesn't know if the object is being used in the same process, across processes, or on an entirely different system. With minor changes, objects built in COM can be used in distributed scenarios. For the test and measurement world, the remote system could be an instrument running an embedded Win32 environment that hosts these COM objects.
The VB developer also can create an ActiveX control that encapsulates the programming model and adds visual controls that aid in setting the initial state of the COM object using Graphical User Interface (GUI) controls. That process previously would have taken multiple lines of programming.
Once proficient in the use of COM, the flexibility factor is seemingly limitless. Many Microsoft applications expose their features' programmability using COM technology. For example, the test and measurement developer can easily take measurements from an instrument and quickly insert them into a Microsoft Excel spreadsheet.
Finally, the environment doesn't lock a user's development efforts strictly to VB. Those COM objects developed in VB can either be used from C/C++, or from more traditional test and measurement visual environments, like Agilent Technologies' VEE and National Instruments' LabVIEW.
Start With Interfaces
When starting with COM, a user needs to begin with interfaces. Interfaces allow the programmer to separate the programmatic interface from an object's implementation. This separation allows COM to be characterized as a binary reuse model rather than a source reuse model found in C++ class hierarchies, which combine both implementation and interface.
Interfaces can be made that correspond to the subsystems found in a SCPI hierarchy. Interfaces additionally facilitate an object-oriented feature called "polymorphism," which allows a programmer to define interfaces that can be applied to dissimilar objects while accessing them in a similar manner.
Currently, the Interchangeable Virtual Instrument (IVI) Consortium is developing a standardization process that will define interchangeable instrument-class interfaces. Once IVI completes its work in this area, each manufacturer of a particular class of instrument (like an oscilloscope) will be able to implement the standardized class interface. Instrument users will then develop their test programs with this interface as the "abstraction," and enjoy the freedom of applying different hardware solutions in their test-system deployment.
Consider the development of a hypothetical test system involving a multimeter. The example instrument server defines a small subset of the Configure, Measure, and Trigger subsystems. The server factors in a new polymorphic interface, called the "IIEE488," to implement the standard IEEE-488 SCPI commands, such as reset and identification. To create a VB interface, the programmer creates a class with methods and properties definitions that don't contain any implementation code in their bodies.
The first step toward creating the instrument server entails invoking the VB development tool and selecting the ActiveX DLL icon in the new-project dialog box. After that is accomplished, the project name is changed from the default name of "project1" to "Multimeter," and the default class of "class1" to "Multimeter34401A."
Creating a new interface consists of selecting the "project" menu dropdown and the menu item Add Class Module. In the dialog that's launched from the menu selection, the developer chooses the new tab, the Class Module icon, and clicks on the "open" button. This action will cause the VB development tool to create a default class with the name "class1." Because a convention in COM suggests the prefacing of interfaces with an "I," the name is set to "IMeasure." The next step would be to define two methods—Voltage DC and Voltage AC (Listing 1).
Of interest in this particular interface is the choice of the Variant type. For range values, the SCPI definition allows the programmer to specify the string values "MAX," "MIN," and "DEF," together with a specific numeric value. To enable this interface to accommodate these potential values, one would use the predefined type Variant that could accept string as well as numeric values. The same process would apply to the remaining interfaces—IConfigure, ITrigger, and IIEE488—as would the filling out of their function prototypes.
After defining all the interfaces, the programmer returns to the first class created—"MultiMeter34401A"—and provides the implementation, using the "Implements" keyword in VB:
Implements IMeasure Implements IConfigure Implements ITrigger Implements IIEEE488
At this point, the VB development environment is set to aid in developing the interface skeletons. As a sample exercise, select the IMeasure object in the object viewer, and select each of the interfaces one by one (Fig. 1).
This creates the interface name as a prefix to the actual method name for each method. In the body of the methods, one would need to send the actual SCPI strings down the I/O transport layer (either GPIB or RS-232). In this scenario, the programmer is using the Agilent I/O object, which is shipped with the Benchlink XL product line. Of interest is the polymorphic "AgtI/OServer" interface that's implemented on those COM objects that layer on top of the NI488, Agilent SICL, and RS-232 libraries. In that interface, the Query, Output, and Enter methods are used. Listing 2 is a sample implementation of the Voltage AC and Voltage DC. This process is repeated for the other methods defined in the IConfigure, ITrigger, and IIEE488 interfaces.
The default interface is kept very simple. There's a "connect" method where the instrument address is passed in; output and enter methods that make calls to the AgtI/OServer interface; and methods that return interface references to the different subsystems. The IMeasure reference method looks like:
Public Function Measure() As IMeasure Set Measure = Me End Function
Once all the interfaces are filled out, the developer selects the "file" menu dropdown and chooses the "make MultiMeter34401A.dll." At this point, the "server" portion of the client-server example is completed.
To build the client code, the developer creates a new project and selects the "Standard EXE" icon in the new project dialog box. Because this is a command- line program, the default form is removed, a module is added, the entry point "main" is created, and the "start-up" object in the project properties is changed to "sub main." Before the multimeter project can be accessed, it needs to be referenced by going into the "project" menu dropdown and selecting the "references" item. This pops up a dialog with the configured COM servers on the system. The programmer scrolls down to the "Multimeter" check box and clicks "OK." The first step that's required is the creation of the object and connection of it with the proper address (Listing 3).
Upon completion of that, the programmer is free to explore the hierarchy. Notice when specifying the instance variable "mm" followed by the "." that a dropdown list appears. This feature in VB is called IntelliSense. When the methods are reached, the IntelliSense feature also will aid in filling out the parameter values (Fig. 2). The real power of IntelliSense cannot be grasped in this example server because the 15-plus example-defined methods could have been combined into a single interface. But, when attempting to model more complicated instruments like an oscilloscope—or completing this current multimeter definition—which have hundreds of commands, then creating hierarchically defined multiple interfaces and navigating these methods with IntelliSense becomes essential.
Earlier, a reference was made to the first value proposition of COM—a binary reuse model. Another powerful feature of COM is location independence. Once the client acquires an interface to a COM object, the client doesn't know if it's communicating with the object in the same process, another process on the same computer, or on another computer entirely. With location independence, the example multimeter server can be accessed in a distributed manner.
Although the server requires no source-code changes, security becomes an issue when objects are to be exposed over the network. This is something the multimeter server programmer cannot solve in code because the programmer doesn't know in advance what security policies are in effect in environments where the server object is to be deployed. Rather, there are tools that allow system administrators to configure security settings for the server object. For this example, the tool used is "OLE View," which is shipped with the VB development environment. OLE View was selected because it allows the required changes to be made that let the created server dll be loaded by a surrogate executable.
Developers can take advantage of the many other features offered by OLE View. In particular, one is its ability to show the MIDL for the interfaces created by the VB development tool for the sample multimeter server object. After OLE View is invoked, the programmer looks for the server program identification (PROGID) under the "all objects" node, which is simply the VB project name, followed by "." which, in turn, is followed by the class name. In this example, the name is "Multimeter.Multimeter34401A" (Fig. 3).
In the example environment, security isn't a key concern. For the other dialog tabs, the programmer sets "Activation" to be the interactive user, "Launch Permission" to include "everyone" and "Access" to include "everyone" as well.
The client must be slightly modified. When creating an in-process version in the previous client example, the programmer used the VB new operator. For the distributed example, it's necessary to use the "CreateObject" function call in order to create the object on a remote system. It has two parameters to consider—the PROGID and the name of the server it will connect to. For an example, see Listing 4. With this minor change, the client program works as before except that it's now spread over two computers.
Access To Instruments Will Change
For the test and measurement world, as instruments begin to embed Win32 operating systems, the way instruments are accessed can be revolutionized by DCOM. For instance, the Agilent Infinium oscilloscope currently uses Windows 98 as its embedded operating system. In the above example, the client made DCOM calls to the remote server object on another computer, which then communicated to the instrument with SCPI over a local I/O transport. In an embedded Win32 environment, the server object could have been hosted inside the instrument directly interfacing to the firmware. The client connects to this programmatic server interface with DCOM to the instrument over a network.
Previously broached was the fact that combining the interfaces with IntelliSense improves the programming model. Another approach to simplifying the model is to layer an ActiveX control object on top of the instrument server to automate some of the programming tasks by allowing the client to modify values through the use of GUI controls. Microsoft currently uses this approach when layering a timer control on top of its timer API.
This particular example consists of layering an ActiveX control on top of the multimeter instrument server to provide support for triggering. The programmer begins with the usual course of starting with the VB development tool, and when the new project dialog appears, the programmer selects "ActiveX Control." Once again, the programmer changes the default supplied VB development tool project name and the "user control" identifier to "MultimeterCtl" and "Multimeter34401Actl," respectively. Next comes the addition of a property called "Address" to aid the user in connecting to the multimeter. The definitions will look like Listing 5.
In addition, we will add controls to the form that allow the user to configure, start, stop, and display a trigger. The control and the configure dialog are shown in Figure 4.
Note that the definition of the range and resolution arguments is improved. In the server API, these arguments were defined as the Variant type. Assurances were made that the user passed in one of the expected strings of "MAX," "MIN," and "DEF." If this example had truly been production code, verification that the argument wasn't of other Variant values, like dates and currency, etc., would have occurred. In the dialog, however, the user can only select one of the predefined string values, or enter a numeric value.
Using the control in a client application, such as a form, entails adding it to the project's components by selecting the project menu dropdown, the component's subitem, and the newly created multimeter control. Once added to the components, the control is taken and dropped on the form. At this point, the property browser has an item in its list for the address property that was implemented. It's set to an appropriate value (Fig. 5).
To access the configure dialog, right-click on the control and select "Edit" from the context menu. Then, modify the appropriate settings, save the project, and run it. The form instantiates with the values that were set at design time and "start" is selected to trigger a new measurement. The result is the "programming" of a triggered measurement without adding a line of code!
Another value proposition of COM is that it's a "language-neutral" environment. This allows programmers to access the objects created in VB from other languages like C/C++, Java, and even COBOL. Rather than providing "header files" for these languages, the environments were modified to read the type library created by the VB tool that was generated from the interface definitions and placed into the executables that were deployed. For C++, a compiler directive called "import" was added to take the type library definitions and convert them to a header file representation. A sample C++ program that exercises the multimeter server can be found in Listing 6.
Yet, the reading of the type library isn't restricted to common programming languages. For test and measurement environments, the development tools of choice are either the VEE or LabVIEW graphical environments. Both have been modified to read COM-type libraries. A sample VEE program that accesses the multimeter server would look like Figure 6.
A derivative of VB, Visual Basic for Applications (VBA), has replaced the proprietary macro languages of desktop applications, such as the Microsoft Office suite and Visio. This allows powerful integration opportunities between the VB Objects that are created and the objects exposed by these desktop applications. For the multimeter example, this involves creating a button on an Excel worksheet that, when pushed, will take a measurement from the multimeter and place it in cell "A1."
To place the button on the worksheet, first activate the "Control Toolbox" by selecting the Excel view menu dropdown, followed by the "Toolbars" submenu. Then, choose the "Control Toolbox." Drag the command button on the worksheet, and change the caption to "Measure Voltage" in the properties window. Double click on the button to be taken to the body definition of the click callback in the integrated VB editor. In the tools menu dropdown, select the references' subitem, and then reference the multimeter instrument server. Add the code in Listing 7 to the body of the callback.
Upon returning to the Excel spreadsheet, exit design mode, and select the newly created "Measure Voltage" button. The measurement is made and the value is placed into cell "A1" (Fig. 7).
To sum things up, COM has moved from an emerging technology to a de facto standard for component communication on personal computers. Because it's a language-independent standard, the developer can choose his or her language of implementation. Putting VB through the paces of COM development—interface design, distributed application, and integration with Microsoft and test and measurement applications—has hopefully demonstrated and confirmed that VB is a natural starting point for COM development.