Archives
 
 
 
  Special
 
 
 
  About Us
 
 
 

Newsletter
Free E-mail Newsletter from BYTE.com

 
    
           
Visit the home page Browse the four-year online archive Download platform-neutral CPU/FPU benchmarks Find information for advertisers, authors, vendors, subscribers Request free information on products written about or advertised in BYTE Submit a press release, or scan recent announcements Talk with BYTE's staff and readers about products and technologies

ArticlesPaths to Platform Independence


January 1994 / Reviews / Paths to Platform Independence

Building applications that run on the Mac, under Windows, in the Workplace Shell, and on the X desktop--from a single set of sources

Steve Apiki

Portability tools won't forever settle the rivalry among the major computing platforms. Debates will continue to rage over whether the Macintosh is really easier to use than Windows, on the merits of Unix compared to Windows NT, or on the future of OS/2. But if you're a developer building applications using a multiplatform toolkit, you won't have to continue to bet your livelihood on the outcome.

Multiplatform toolkits provide an API and a set of libraries that allow you to develop an application one step removed from the underlying operating system. All four toolkits I'll review here provide these libraries for Windows, the Mac, X/Motif, and OS/2 Presentation Manager; some support many more platforms. When you build your application on top of the footing provided by these tools instead of directly on the underlying GUI, your software can run in a more-or-less native manner on whatever platforms the toolkit supports.

Common Groundwork

Fundamentally, all GUIs share a common groundwork: Whether you are running on a Mac or on OS/2, there are always elements like windows and dialog boxes. And all native GUI APIs provide ways to control these elements, as well as provide methods for handling other graphical entities like icons and bit maps. So all these toolkits must, at the very least, abstract these capabilities. But there are also fundamental differences among GUI operating systems, such as differences in file structure and platform-specific features like the Windows MDI (Multiple Document Interface) or the Mac's single-system menu bar. Effective abstraction means providing a single API that allows an application to act differently on each platform, to look and act the way you expect native applications to look and act.

I used each of these toolkits to build the guts of an application I've been wanting to write for some time, a simple spreadsheet-like tool that handles text formatting for tables. These packages really are toolkits--besides the library itself, each product (except C++/Views 2.1) provides a tool for building applications elements (e.g., menus and dialog boxes) graphically and for hooking code to these graphical elements. I built the graphical structure of the table editor using the resource editor or prototyper each development environment provides. After doing the initial development under Windows, I ported the applications to the Mac, OS/2, and X/Motif (OSF/Motif from Integrated Computer Solutions running on Solaris 2.1).

I found that each of them will serve: All of them let you build real GUI applications with fairly sophisticated features and let you take an application across platforms with only a few twe aks. The difference is where each package chooses to make the trade-off between the ease with which you can get to that final port and the level of platform-specific customization you can provide when you're through.

C++/Views

-- Outstanding development environment based on a SmallTalk-like browser

-- Simple programming model provides full GUI coverage and includes non-GUI

objects

-- Closed system makes it more difficult to migrate existing projects or manage

projects with multiple programmers

Liant Software's C++/Views is a high-level, strongly object-oriented multiplatform toolkit. Its dazzling array of classes abstract not only the underlying GUI but also the entire framework of an application, from classes that represent objects as real as buttons and windows to those that represent abstractions like collections and sets.

C++/Views is like SmallTalk both in its set of classes and in the way it lets you design your applications. You work with C++/Views through a class browser. The browser presents C++/Views' entire class hierarchy in a window; you build your application by choosing appropriate classes out of the hierarchy and deriving appropriate classes from them.

I built the table editor as an MDI application (C++/Views supports MDI functions on all supported platforms) by deriving my main window from C++/Views' MDI-application class. When you derive a class, C++/Views creates new C++ source and header files in the background. It presents class members in another window and lets you view headers or edit member functions in a third. During the entire application-building process, you never see an entire source file; your view on the project is always through the browser's class orientation. The result is a much clearer view of the overall structure of your application, and it's easier to focus on the design of the application, rather than the drudgery of keeping track of C++ source and header files.

The high-level classes in C++/Views can mask the s tructure of the underlying GUI. Although there is an event class for handling system-specific events, I never had to worry about these low-level events when building the table editor. Instead, I just built member functions like paint() and mouseDn() to override the default members of the window class from which I derived my view window and responded to those events inside those functions.

Despite its high level of abstraction, C++/Views makes concessions to more procedural techniques when it makes sense. To open a standard file status dialog box, for example, you call a static member function of the file status dialog box class, which simply constructs a modal file dialog box and returns when the dialog box is complete.

C++/Views is currently shipping in two distinct versions: 2.1 and 3.0. The differences between the two are significant enough to have an impact on the way you build your applications. Version 2.1 totally lacks resources; you have to build menus, dialog boxes, and other objects th at are usually built from resource templates from scratch, programmatically. Although C++/Views provides classes (e.g., dialog box and menu-handling classes) that reduce some of the work involved, this is still a serious lack.

Version 3.0 fixes this problem (and goes well beyond) by adding persistent object storage, which not only gives you a mechanism for storing these menu and dialog box objects but also gives you a repository for objects of your own design.

Version 3.0 also adds a nicer browser interface (e.g., adding the capability to find a class, rather than searching the hierarchy as you must do in 2.1) and a resource editor. Unfortunately, version 3.0 was only available on the Windows platform as this article went to press, so it wasn't very useful as a cross-platform tool. Liant plans to ship Mac, Presentation Manager, and Motif versions by the beginning of this year.

Even in version 2.1, C++/Views is a great environment; almost good enough to choose regardless of its multiple-pl atform support. It was the most immediately productive toolkit in this review. But even though it is excellent for single-user projects, C++/Views abstraction of the collection of source files makes it difficult to coordinate work among several programmers on a single set of sources and to migrate an existing set of C++ sources into the environment (although it has an import utility).

Some minor pieces are missing (e.g., the ability to add bit maps to menus) and some extra strengths (e.g., great handling of fonts and text). I found C++/Views an outstanding tool, but ultimately, your reaction to C++/Views will depend on whether you're willing to work at a considerable distance from the underlying native GUI for the gain in simplicity of design.

WNDX

-- Can create GUI styles independent of host environment

-- Some native features hard to reach

-- Comprehensive set of GUI elements

With most multiplatform libraries, the underlying interface is abstracted into elements like the scr een, windows, and controls. As a programmer, you don't know whether or not the scroll bar that's sending you messages is a Windows-style scroll bar attached to the window frame or a Motif-style proportional scroll bar. WNDX takes a different approach by emulating non-native window elements on all the platforms it supports--if you want to work with a Motif-style interface, WNDX will create it for you even if you are on Microsoft Windows. This is a slick feature, and it works well, but unless you want an application that will look and feel exactly the same on Motif as it does under Windows, you are probably better off sticking with native controls, which WNDX also supports.

Ironically, although WNDX can add non-native behavior, it's difficult to get to some native functions. For the table editor, I wanted a view window with horizontal and vertical scroll bars attached to the window frame, an interface feature that both the Mac and Windows support directly. However, there is no style that lets you do this under WNDX, and I ended up having to float scroll bars near the edge of the window to emulate this behavior in my program. Since I couldn't get system scroll bar widths on the WNDX for Mac beta version I tested (a shortcoming WNDX says will be addressed shortly), the scroll bars I tried to draw in the usual scroll bar area didn't quite fit or look like Mac scroll bars.

In addition, WNDX's full customization extends to icons; therefore, it provides a set of icons to which you can refer inside the library (other resource template information is stored in an ASCII file that ships with your completed application). The icons can look a little out of place, for example, in a Windows MDI window. If you want to add native icons, you have to tack them on in a platform-dependent manner.

The positive side to customization is a rich set of built-in windows objects, like 2-D lists that work almost exactly like Macintosh lists. I couldn't use lists as a base for the table editor because I wanted a grid that appeared to be infinite; however, the WNDX list supports almost every other behavior I wanted for the table editor and would be good for simple spreadsheets.

In the design of the WNDX library, almost all Window behaviors are controlled through attributes. WNDX elements have some degree of object orientation: WNDX elements that share common attributes are plug-compatible since you get and set all attributes through a common interface. But I found working within this framework a little disorienting for two reasons: First, because the attribute list is so large, it's hard to find the attribute you want to set when you aren't an experienced WNDX programmer, and second, I found it unnatural to initiate what I would think of as an action (e.g., moving a window) by setting an object's position attribute. However, the WNDX API is large, and in addition to handling every GUI event, there are many cover functions (e.g., WND_Move()) that mask the attribute setting calls. Once you get a handle on the API, programm ing WNDX is straightforward. The main() function handles and dispatches events to other parts of the system; you trap those events through callbacks and then you respond.

You can create resources and set up callbacks using WNDX's OPUS prototyping tool. OPUS was probably the weakest prototyper among those provided with these libraries. There's little layout support in dialog boxes (i.e., no alignment or spacing capability), and OPUS doesn't build make files for its projects. You have to run an external mkmake utility that builds a simple make file from the sources themselves.

XVT

-- Complete platform coverage and the most well-supported API

-- Uses native resources built from common scripts

-- API familiar to Mac and Windows programmers

XVT Software's XVT doesn't really have any razzle-dazzle features--no object orientation, no low-level customization, and no emulation of non-native controls. But it has what I'd consider most important: an obvious and comprehensive API, a great design tool, and third-party support that the other products don't approach.

If you're already familiar with Mac or Windows programming, you probably won't find a more comfortable API than XVT's. The programming model of XVT is close to that of the Mac, and I was able to transition more easily to XVT from full-time Windows programming in C than to any other cross-platform tool.

XVT's resource handling is also the simplest; you build resource templates for XVT's resource format using a simple resource description language, or by using the design tool, XVT-Design. Once a resource is built, you use CURL (XVT's resource compiler) to build a native binary format that gets attached to the executable file. XVT's greatest shortcoming in resource handling is a lack of support for bit-map formats that can move between platforms; an upcoming release of XVT should address that problem.

XVT-Design is an easy-to-use resource editor and prototyping tool that builds entire projects, including URL (Unive rsal Resource Language) files (for resource compilation by CURL), source files, and make files. You can attach common event handlers like XVT standard dialog box functions directly within XVT-Design, and you can also type entire procedures directly into the editor, although I found it easier to edit templates later in a more standard fashion.

XVT-Design can automatically include File, Edit, and other standard menus in your resource file. XVT-Design also has a built-in Font menu that goes nicely with XVT's transparent handling of system-independent fonts.

Besides fonts, XVT also handles help information in a portable, standardized way. However, the format of the help file is rudimentary (it handles only one level of help, and there's no real index), so you may be better off skipping this standard feature.

Most cross-platform toolkits don't abstract memory handling very well, so moving between a 32-bit flat model to a segmented pointer architecture can be messy. If you know you are going to need large memory objects (as I'd like to be able to handle for the table editor), you can use XVT's global allocation functions to get handles to memory that can extend past 64 KB. This is slow under 16-bit Windows, but the protection from faults when moving from platform to platform is worth the trouble for a few large objects.

Had XVT Software released its promised PowerObjects custom controls in time for this evaluation, I would have based my table on a spreadsheet PowerObject. As it was, I ended up building a more limited table in my own code.

Where XVT falls shortest versus C++/Views and Zinc is in customization. The C++-based systems, both of which provide source code, are readily customized, while XVT's C-based library is not. As I wrote this review, XVT Software was nearing release of Power++, its C++ product. Power++, unlike XVT++ (XVT's earlier C++ product), is a high-level application framework that will eventually form a foundation for PowerObjects. It won't yet bring XVT into the highly abstracted realms occupied by C++/Views and Zinc Application Frameworks.

Nevertheless, XVT today is the most straightforward and stable path between Windows and Mac programming and programming to an abstract GUI. Pending improvements like portable bit maps and PowerObjects will make XVT an even stronger contender.

Zinc Application Frameworks

-- Totally flexible and configurable framework

-- Event-centered class model is complex and difficult to learn

-- Excellent collection of window objects for input

Both Zinc and C++/Views are based on C++, but the similarities end right about there. While C++/Views takes a very high-level, abstract view of the problem domain, Zinc uses the benefits of C++ to provide powerful customization features and an extensible, extremely flexible API.

Zinc abstracts low-level features such as devices, window objects, and events; it does not abstract event handling for every window object. In fact, direct handling of events are the model i n Zinc--you handle system events, logical events sent by Zinc, and even use events sent through the event queue to communicate with other objects inside your program.

This abstraction of features like events and devices makes handling custom behaviors on different platforms easy; you can get a logical event from the system that tells you to redisplay a window, or you can translate the actual WM_PAINT message that it represents when you're running on Microsoft Windows. You can build a single executable file that can handle DOS graphics and DOS text simply by setting the appropriate virtual display; all the other code in your system remains intact.

It's not all low-level. Zinc does provide powerful, high-level classes like toolbars, and a systemwide help system that allows you to maintain context-sensitive help just by assigning help contexts to objects. Zinc also has the most complete collection of input objects, like formatted strings and other windows objects that can verify entry. And Zinc's w indow objects are true objects, so they connect together as easily as Lego blocks. For example, you can build a scrolling list box with text objects, then use the same code to present a list box that includes bit maps. You just have to hand bit-map objects to the list box instead.

One of Zinc's most powerful features is its object repository, which stores resource-type and other objects in a persistent object database. The Zinc Designer, Zinc's analog to a resource editor, actually instantiates these objects as you work interactively with the design. The database is hierarchical, which lets you store multiple, linked copies of objects, say one menu object in English and another in Spanish, for later retrieval. In upcoming releases, Zinc plans to add unicode support to accommodate double-byte languages.

Unfortunately, all this flexibility gives Zinc a steep learning curve. It's always hard to find the handle on C++ application frameworks, because it takes some time to know where you should look f or the entry point in a class hierarchy. C++/Views addresses this to some extent with the browser, but there is no similar feature in Zinc.

I got most of my sample application done using Zinc, but I confess that I never knew whether I was using the best design to handle a problem or whether I'd used the right class or done things the easiest or most efficient way. Keeping track of events and grappling with the class hierarchy was a daunting task. If you have the time to learn it well, Zinc is potentially the most powerful package in this collection; however, don't expect to become skilled at Zinc programming quickly.

Cross-Platform Picks

Choosing a cross-platform development environment is not a trivial undertaking. Once you've made the choice, you will have to commit a great deal of development effort to building code that is completely dependent on the toolkit and the toolkit's future. But that investment is made worthwhile by the elimination of learning new native APIs and by the effort sa ved in not having to maintain multiple code bases.

The payoff to this investment makes learning even a complex package like Zinc potentially worthwhile. Or, if you're looking to C++ to provide an elegant, design-focused development model, C++/Views would be an excellent choice. But I'm going to finish only one version of my table editor, and I'm going to do it in XVT. XVT's simple API, strong tools, and strong industry-support guarantee that the time and money invested in shifting to a platform-independent GUI will pay off in reduced effort down the road.


The Facts



Liant Software
(C++/Views)
959 Concord St.
Framingham, MA 01701
(800) 237-4873
(508) 872-8700
fax: (508) 626-2221


The WNDX Corp.
(WNDX)
1550 8th St. SW, 
Suite 305
Calgary, Alberta,
Canada T2R 1K1
(403) 244-0995
fax: (403) 244-1030


XVT Software, Inc.
(XVT)
4900 Pearl East Circle
Boulder, CO 80301
(800) 678-7988
(303) 443-4223
fax: (303) 443-0969


Zinc Software, Inc.
(Zinc Application Frameworks)
405 South 100 E
Pleasant Grove, UT 84062
(800) 638-8665
(801) 785-8900
fax: (801) 785-8996


Screen: Programming with C++/Views means working within a complete development environment, based on a C++ class browser. C++/Views 3.0 is much more sophisticated than the last version (2.1), with a resource editor for persistent objects and much better class navigation. However, it's currently only available on Windows.
Screen: WNDX is a superset API that provides full GUI object support and even lets you choose an interface style that's independent of the host environment (if you'd like). However, WNDX's OPUS (shown here) lacks many of the layout features that a resource editor requires.
Screen: XVT-Design adds a strong resource editor and prototyper to an already solid API. XVT doesn't have the most sophisticated or elegant programming model but working in it will come naturally to developers familiar with the Mac or with Windows.
Screen: Although it looks like the other applications design tools presented in this collection, Zinc Designer is not a code generator in the conventional sense. Instead, it's a tool for editing objects inside Zinc's persistent object database, one of which you ship with every application you build with Zinc.
Table: MULTIPLATFORM TOOLKITS A portable development tool has to cover your requirements for platform support. XVT and Zinc have the most complete coverage, but if you don't need to handle some of the more exotic platforms, WNDX and C++/Views cover the most popular desktop systems. (This table is not available electronically. Please see January, 1994, issue.)
Steve Apiki is senior developer at Appropriate Solutions, Inc., a Peterborough, New Hampshire-based consulting firm specializing in cross-platform development. He is also a BYTE contributing editor. You can reach him on the Internet or BIX at apiki@bix. com .

Up to the Reviews section contentsGo to next article: Opening Night for Premiere 3.0
Flexible C++
Matthew Wilson
My approach to software engineering is far more pragmatic than it is theoretical--and no language better exemplifies this than C++.

more...

BYTE Digest

BYTE Digest editors every month analyze and evaluate the best articles from Information Week, EE Times, Dr. Dobb's Journal, Network Computing, Sys Admin, and dozens of other CMP publications—bringing you critical news and information about wireless communication, computer security, software development, embedded systems, and more!

Find out more

BYTE.com Store

BYTE CD-ROM
NOW, on one CD-ROM, you can instantly access more than 8 years of BYTE.
 
The Best of BYTE Volume 1: Programming Languages
The Best of BYTE
Volume 1: Programming Languages
In this issue of Best of BYTE, we bring together some of the leading programming language designers and implementors...

Copyright © 2005 CMP Media LLC, Privacy Policy, Your California Privacy rights, Terms of Service
Site comments: webmaster@byte.com
SDMG Web Sites: BYTE.com, C/C++ Users Journal, Dr. Dobb's Journal, MSDN Magazine, New Architect, SD Expo, SD Magazine, Sys Admin, The Perl Journal, UnixReview.com, Windows Developer Network