Table of Contents
In this chapter, we will review briefly key components of the VR Juggler Portable Runtime (VPR) that will be used by Gadgeteer device driver authors. This chapter is not meant to be a comprehensive description of VPR but rather a small guide to be used by programmers new to Gadgeteer, VPR, and other modules used by VR Juggler. We assume that the reader has some familiarity with operating system programming, in particular with serial device I/O, socket I/O, and multi-threaded techniques. One or more of these will almost certainly come into play when writing a device driver for use with Gadgeteer.
For those developers new to Gadgeteer and VPR, VPR provides an cross-platform, object-oriented abstraction layer to common operating system features. VPR is the key to the portability of Gadgeteer, Tweek, VR Juggler, and other middleware written at the Virtual Reality Applications Center. It has been in development since January 1997, and it has grown to be a highly portable, robust tool. Software written on top of VPR can be compiled on IRIX, Linux, Windows, FreeBSD, and Solaris, usually without modification.
Internally, VPR wraps platform-specific APIs such as BSD sockets, POSIX threads, and Win32 overlapped I/O. Depending upon how it is compiled, it may also wrap the Netscape Portable Runtime (NSPR), another cross-platform OS abstraction layer written in C. By wrapping NSPR, VPR provides developers with an object-oriented interface and gains even better portability. These details are all hidden behind the classes that make up VPR, and users of VPR do not need to worry about platform-specific details as a result.
Before discussing features of VPR useful to device driver authors, we must first understand how I/O is handled in VPR. All I/O classes (file handles, serial ports, and sockets) share the base class vpr::BlockIO. Reads and writes are performed using blocks of memory (buffers). This design provides an API that more closely resembles that of the underlying operating system (with methods called read() and write()), but it is in contrast to stream-oriented I/O that is usually seen in C++. Streams could be written on top of the buffered I/O classes, but thus far, the need has not arisen. With this in mind, the design provides an API that is immediately familiar to programmers used to POSIX-based interfaces, but the API may seem clumsy to C++ programmers who are accustomed to using std::ostream and friends.