No mirrors and magic here -- You can write common code for Unix and NT
Building a common code base will speed porting and reduce the learning curve. In part 1, we alert you to differences between the operating systems as we take you through the NT API-on-Unix development approach
For dyed-in-the-wool Unix shops, there's good news and there's bad news regarding Windows NT. The good news is that NT is not likely to displace Unix as the operating system of choice for hosting major enterprise databases and other serious applications in the next few years. The bad news is that NT is not going to go away, and the chances are you will have to come to grips with it in the not too distant future. In this article, the first of two, we look at how you might evolve a unified development strategy for Unix and NT. In the second article we will examine the practicalities of porting applications from Unix to NT and other Unix/NT coexistence issues. (2,000 words)
One of the key challenges every developer faces is picking a platform for application development. Today, developers of commercial applications are increasingly having to choose between Unix and Windows NT.
In deciding on a strategy to achieve a relatively common code base for Unix and Windows NT, we have three options. First, we could use some well-established standard that is independent of but supported by both systems. Unfortunately, no such de facto or de jure standard exists. There are a number of proprietary GUI and application builder products that support both NT and Unix, and these could be used to implement such a strategy.
One seemingly obvious approach would be to develop code using
ifdefs to conditionally compile the appropriate
application programming interface (API) calls depending on the
platform. However, the architectural and API differences between the
two operating systems are so significant that virtually none of the
GUI programs (except for the most trivial ones) could be maintained
if developed in this manner.
Therefore, we are left with either basing our development on the Unix API or the NT API. In fact, both these options are available through third-party tools and libraries. Unix APIs on NT are supported by DataFocus' Nutcracker toolset. NT APIs on Unix are addressed by Wind/U from Bristol Technology and MainWin from Mainsoft. At the moment, the NT API-on-Unix approach has the upper hand and consequently, it is this approach we will examine here.
Adopting Microsoft's architecture may be hard to swallow for some Unix sites. In practice, this should not be too painful for new developments, but existing Unix applications will have to be rewritten to the Win32 model.
So how different is NT anyway?
The past few years have seen great strides in Unix compatibility. We now have the Common Desktop Environment (CDE) that is portable among the major Unix vendors' platforms. If you have not been tracking NT closely, you could be forgiven for assuming that it would largely adopt Unix-based standards. But alas, this is not so.
It is true that NT provides a so-called POSIX environment, but in many peoples' opinion this was simply included to meet requirements for tendering on government projects; it only provides 1003.1 functionality. Consequently, NT POSIX is only suitable for console (dumb terminal) applications that do not use the NT GUI. NT POSIX applications also can't use native NT networking. No serious NT application designer would choose NT's POSIX environment to develop mainstream NT applications. There are better extended POSIX implementations available from third-party vendors such as OpenNT from Softway Systems Inc.
Most NT applications are developed using the native API, known as Win32. In fact there are at least three variants of Win32. Initially, there was Win32s that was designed to allow 32-bit application development on 16-bit Windows 3.x. Win32s uses a technique known as thunking to convert 32-bit parameters to and from 16-bit parameters. These days we can safely forget Win32s. Both Windows 95 and NT support Win32. Broadly speaking, NT is the full implementation while Windows 95 is a slightly stripped-down version. For example the Windows 95 Win32 implementation does not support asynchronous I/O or event logging, in addition to a number of other features. In these cases, the API calls are still in Windows 95, they just don't do anything. Windows 95, however, introduced a number of Win32 API calls that were not in NT 3.51.
The general consensus is that Microsoft's Visual C++ is the language of choice for NT and Windows 95 development. Bristol's Peter Ambrose estimates that Visual C++ is used for more than 80 percent of NT projects. Along with Visual C++ comes the Microsoft Foundation Class library (MFC). MFC provides a huge volume of code to build applications for the Win32 environment and, in fact, many Win32 API calls are hidden by use of MFC.
The Visual C++ toolset is known as the Developer Studio and provides powerful rapid application development capabilities. To get started, developers use the AppWizard to define the type of application, such as console, single document, or multidocument. Having done this, visual editors are used to create dialog boxes, menus, and other GUI objects. Next, the Class Wizard is used to build processing code for objects, such as dialog responses or menu choices. This produces a runable skeleton application, often without the developer typing in a single line of code!
What about using C? Visual C++ will compile C code, although making Win32 calls is no problem in C. However, using C precludes the use of MFC, and that essentially is the key to Developer Studio. Consequently, any Unix shops still using C will have to standardize on C++ if they want to make full use of the available development tools for a common Win32 code base.
In choosing to use the Win32 model, programmers accustomed to Unix will need to change the way they design applications. There are a great many differences in the architecture of the two operating systems. A few are listed below:
forkAPI call to duplicate a process. Often
forkis used by servers to create handler processes to carry out some task. Typically the forked process will issue an exec call to run a new program to handle the required task. Win32 uses the single
CreateProcessAPI call to create a new process and to specify an executable image to run in that process. The preferred way of implementing such systems on NT is to use threads. Of course threads, in the form of POSIX Pthreads, are available on most modern Unix implementations. The NT threads API calls are not compatible with Pthreads, although functionally they are quite similar.
fopen()are available in the NT environment. However, the more sophisticated NT I/O features, such as 64-bit file access, asynchronous I/O, and the signaling of I/O completion, require that you use the Win32 APIs (
It is a given in Unix that file descriptors 0, 1, and 2 represent
respectively. Win32 uses handles rather than descriptors,
and you can't assume them to be fixed as in Unix. In fact there is a
Win32 API call,
GetStdHandle(), to find out what the
Data, as well as code, might need to be common to both Unix and NT. There are some potential issues here as Intel processors are little endian whereas many Unix processors, such as SPARC, are big endian. In Windows, text file lines are terminated by a line feed and a carriage return. Unix uses only line feed to flag an end of a line. Some applications require the line feed/carriage return termination to work correctly.
Another issue is file naming. Unix uses the forward slash (/) as
a directory separator, and Windows uses the backslash (\). Unix
file names are case sensitive, and NT filenames are not. Lastly, the
Unix file system appears to be a single directory hierarchy whereas
NT storage is divided into a number of physical or virtual disk
drives with a directory hierarchy on each. To access a file on NT,
you must know what disk drive the file is on and specify the drive
letter (C:, D:, E: etc. ) as part of the file's pathname. Special
coding can be used to circumvent some of these problems. For example
GetVolumeInformation() call can be used to
determine the file system characteristics such as maximum permitted
file name length and case sensitivity.
NT porting to Unix
According to the tools vendors, the steps in porting an NT application to run under Unix are roughly as follows:
There could be various problems that need to be resolved in the NT code to allow it to be used on both platforms. These can be simple syntax issues, like the fact that Visual C++ allows an extra semicolon at the end of class definitions. This must be removed for most Unix C++ compilers. Also, Visual C++ allows derived classes to access base class private members whereas in most Unix implementations, the member must be declared as "protected" to allow access. There might also be dependencies on Intel hardware that must be detected and recoded. Ideally, all these issues should be resolved in such a way that the end product is a single set of source code for both platforms.
Who makes the tools?
Bristol and Mainsoft enjoy close working relationships with Microsoft. They have access to the source of the MFC library and other Microsoft code under license. It therefore is not surprising that Microsoft is happy to work closely with such vendors as they are helping to extend the Microsoft world beyond the PC. It should be noted that these products do not make Microsoft's Visual C++ available under Unix. Rather, the Win32 and MFC APIs are implemented on the Unix platform. A native Unix C or C++ compiler must be used to compile the code for both products.
Bristol's Wind/U supports Win16 with MFC 2.5 and Win32 with version 4 of MFC. Microsoft itself is using the Wind/U tools to port its Internet Explorer to various Unix platforms. Digital Equipment Corp. (DEC) commissioned the development of a version of Wind/U (Wind/VMS) for its OpenVMS. All the Wind/U features are provided as libraries that the application is linked against after successful recompilation using the native Unix C or C++ compiler. Consequently, the applications are, strictly speaking, native Unix applications.
Mainsoft's core tools are similar in concept to those of Bristol. The MainWin Studio is a set of cross-platform development tools for NT and Unix. It includes MainWin XDE (eXtended Development Environment), MainWin Help (the Microsoft Help engine on Unix, included with MainWin XDE), MainWin Test, and Visual SourceSafe for Unix. These latter two products are ported versions of Microsoft Test and Microsoft Visual SourceSafe products.
About the author
Dave Herdman is a principal with Open Systems Interconnections Ltd., a consultancy and reseller based in London. Herdman speaks often at industry conferences in Europe on Unix. Reach Dave at email@example.com.
If you have technical problems with this magazine, contact firstname.lastname@example.org