A common way to program a device is through the functions included in the low-level driver
of the interface card used to connect the computer to the device. Generally the low-level
driver is a library (a DLL on Windows systems) of functions that the programmer can call
from his main program or from a custom instrument diver.
In the following example, the functions ibwrt() and ibrd() are parts of the NI-488.2M library
issued by National Instruments. These functions allow an application to send (ibwrt) a command to a GPIB device
and to read (ibrd) some data from it. Using the functions of the stdio library, a typical
C
pattern could be the following one:
char resp[100];
char cmnd[100];
int myInstr = ibfind("VMETER") //1
sprintf(cmnd, "MEAS:VOLT:AC? %f,%fn", range, resol); //2
ibwrt(myInstr,cmnd, strlen(cmnd)); //3
ibrd(myInstr, resp, sizeof(resp)); //4
resp[ibcntl] = '0'; //5
sscanf(resp, "%f", &reading); //6
The goal of this code fragment is to communicate with a voltmeter that is connected to the computer through a
GPIB card. The code sends the voltmeter the device-dependent message "MEAS:VOLT:AC?"
The code then acquires, parses, and stores the response in
the variable named reading.
This is the sort of code one would write, assuming he had access only to a
compiler and the vendor's low-level driver. Certainly this code is not self-explanatory.
Nor is it especially good code --
it isn't safe because of array dimensioning issues, there is neither static nor dynamic type-checking...it
simply isn't a good example of using the C++ language.
However, the main disadvantage
is that it is very difficult to port this code to another platform. What happen if
we switch interface cards? What if we migrate from Windows to Linux? Probably a C++ programmer
would use streams if he could. But the C++ Standard Library directly supports
only in-memory formatting and parsing, file and terminal I/O. However the new standard IOStreams
can be extended and customized. In other words, one can specialize entire streams providing
support to any kind of external device or communication channel. So the proposed framework will
extend the standard IOStream to support a generic (read as platform-independent) GPIB interface.
Under this standard, we can write much better C++ code:
NI_488::gpibstream myInstr("VMETER");
myInstr << " MEAS:VOLT:AC?" << range << "," << resol << endm;
myInstr >> reading;
That is certainly safer, more portable, simpler, easier to maintain, and easier to understand than the code in the previous example!