Watcom's C++ 10.6 comes with the standard components expected of a modern GUI compiler. Visual Programmer, debugger, browser, profiler, source editor, resource editor, Spy, DDESpy, Heap Walker, and Zoom are part of the list. The Watcom product also includes a licensed version of MFC 3.2 with source code. Although the following example does not use MFC, it should be a straightforward task to compile one of the sample plug-ins in this book that uses MFC.
Compared to other Integrated Development Environments, Watcom's IDE is somewhat less integrated than Microsoft or Borland. Both the debugger and the resource editor are located outside of the IDE. Watcom's real power probably lies under the hood with tight, fast code generation. Powersoft (makers of Watcom C++) has announced something called Optima++ Developer. This is a rapid application development (RAD) environment that simplifies the use of C++ and Java languages to build client/server and Web-enabled applications. Time will tell whether Optima++ is appropriate for developing plug-ins.
In any case, with a few tweaks the current Watcom IDE is quite capable of generating a plug-in for Netscape's Navigator.
This example builds on the MCIWnd sample found previously in the book and on the CD-ROM. Refer to Chapter 20, "A Plug-In with MCIWnd," for more details on its implementation. If you want to build this example, get the files shown in the following lists from the CD-ROM and put them all in a single directory.
For the \CODE\MCIWND directory, you need these files:
For the \CODE\INC directory, you need these files:
For the \CODE\COMMON directory, you need this file:
Put all files in the same directory to match this example.
For the Watcom compiler, you need to make a few changes to the source files. First, change the include paths to local. Then, change the syntax for the sizeof operator in NPWIN.CPP. Finally, change the entry point definitions. The next three sections detail these changes.
After you copy the files to a new directory, change the header include paths. All the CPP files except stdafx.cpp include a relative path for stdafx.h. Change these to local:
#include "..\inc\stdafx.h"
should be
#include "stdafx.h"
In the file npwin.cpp, put parentheses around NPPluginFuncs where it is used with the sizeof operator.
Change the line
if (pFuncs->size < sizeof NPPluginFuncs)
to this:
if (pFuncs->size < sizeof (NPPluginFuncs))
Again in npwin.cpp, change all three entry point definitions.
Change the lines
NPError WINAPI NP_EXPORT NP_GetEntryPoints(NPPluginFuncs* pFuncs)
NPError WINAPI NP_EXPORT NP_Initialize(NPNetscapeFuncs* pFuncs)
NPError WINAPI NP_EXPORT NP_Shutdown()
to these:
extern "C" NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* pFuncs)
extern "C" NPError WINAPI NP_Initialize(NPNetscapeFuncs* pFuncs)
extern "C" NPError WINAPI NP_Shutdown()
The next three sections give step by step instructions for creating a plug-in from scratch with Watcom's IDE. The first section shows you how to set up a new project that creates a Windows plug-in DLL. The next section shows how to build the plug-in. Lastly, the third section covers testing and debugging your Watcom-built plug-in.
To set up your project for a Watcom-based plug-in, you need to create the project, set the target, add the proper source files, create a librarian command file, and change some compiler and linker switches. Steps 1 through 7 detail these tasks.
After starting Watcom's IDE by double-clicking on the IDE icon, create a new project with the File|New Project main menu item. Name the new project npmciwnd.wpj, and create it in the directory in which your modified files are stored. In Figure 28.1, you can see the Enter Project Filename dialog for this information.
Figure 28.1 : Project name and location.
Name the new target npmciwnd and select environment Win32. Make the Image Type Dynamic Link Library (.dll). If you plan to use MFC later on, you should select at that time MFC-32bit (3.2) in the dialog shown in Figure 28.2.
Figure 28.2 : Target Name, Environment, and Image Type.
Now that you have a new project, add source files with the Sources|New Source main menu item, as shown in Figure 28.3.
Figure 28.3 : The New Source menu item.
When the Add Files dialog appears, add the files npmciwnd.cpp, npshell.cpp, npwin.cpp, and npmciwnd.rc, which are the source files needed for the MCIWnd example. Just click the Add All button as shown in Figure 28.4.
Figure 28.4 : The Add Files dialog.
The Watcom Resource Editor is not capable of generating a version resource. No problem. Just use the .rc file from the Microsoft example and change it in the text editor. Watcom's resource compiler generates the proper resource from the Microsoft-produced file. You need not change the .rc file for this example. In Figure 28.5, the plug-in specific resources are shown in highlighted text.
Figure 28.5 : Verifying the .rc file.
Create a librarian command file for the Watcom linker. Each line in this file corresponds to an exported DLL routine. The format for these lines is as follows:
++sym.dll_name[.export_name][.ordinal]
In this format, sym is the name of the symbol in the DLL, dll_name is the name of the DLL, export_name is the external name of the export, and ordinal is the ordinal number that can be used instead of the name.
To be consistent with this example, name this file export.lbc. Watcom uses a library command file instead of a .DEF file to define DLL entry points. The contents of this file, as you can see in Figure 28.6, should be the following three lines:
Figure 28.6 : The contents of the Librarian command file.
++_NP_GetEntryPoints@4.npmciwnd.NP_GetEntryPoints.1
++_NP_Initialize@4.npmciwnd.NP_Initialize.2
++_NP_Shutdown@0.npmciwnd.NP_Shutdown.1
| Note |
Those funky ampersands followed by numbers are notation for the __stdcall alias. With __stdcall, all C symbols are suffixed by @nnn, where nnn is the sum of the argument sizes. The library command file names these symbols to the proper external name. You can see the symbol names in your .map file. |
Bring up the C++ Compiler Switches dialog with the Options|C++ Compiler switches main menu item. Figure 28.7 shows the location of this menu.
Figure 28.7 : Bring up the C++ compiler switches.
Your plug-in needs to use stack-based calling instead of register-based calling as a default because the Navigator directly calls your plug-in APIs. Navigator expects stack-based calling conventions. In Figure 28.8, you can see the compiler switches "10. Memory Model and Processor Switches" with 80386 stack-based calling selected, along with the default 32-bit flat memory model.
Figure 28.8 : Setting to 20386 stack-based calling.
Bring up the linker switches dialog with the Options|Link Switches main menu item. Under the Export names section, fill in the name of your previously created export.lbc file with a leading equal sign. In Figure 28.9, the Export name is set to =export.lbc.
Figure 28.9 : Adding the export definition file.
To build the plug-in, the next two steps show how to start a full build and check the output for errors.
With the Target|Make main menu item, start building the plug-in. Figure 28.10 shows the location of this menu item.
Figure 28.10 : Building the plug-in.
A number of warnings are printed from nonreferenced symbols. Don't worry about these. Look for any fatal errors. In Figure 28.11, you can see these warnings.
Figure 28.11 : Checking for errors.
The Watcom debugger, unlike the Microsoft and Borland debuggers, is a separate debugger. To test your plug-in, you need to change the debugger's startup directory, load and run Netscape, set any breakpoints, and then restart the Navigator. Watcom's debugger requires this first Navigator load so that you can set breakpoints for the second run. Steps 1 through 8 detail these instructions.
When you have successfully built the plug-in DLL, copy it to the plugins directory under the Navigator program. After that, open the Properties of Watcom's Windowed Debugger.
To make it easy for the debugger to find your source files, make the start directory your plug-in's source file directory.
Start the debug session by browsing for netscape.exe. Click OK when it is found. Figure 28.12 shows the New Program dialog used to start Netscape.
Figure 28.12 : Loading netscape.exe.
You need to load the plug-in twice in order to set a breakpoint. For the first time, select Run|Go on the main menu (see Figure 28.13).
Figure 28.13 : The Run/Go menu item that is used to run Netscape.
While the Navigator is up, make sure that the plug-in's resource data is correct by bringing up the About Plug-ins dialog with Help|About Plug-ins (see Figure 28.14).
Figure 28.14 : Bringing up About Plug-ins.
For this plug-in, About Resources should show MIME types of audio/x-midi, audio/x-wav, and video/x-msvideo. You can see these MIME types in Figure 28.15.
Figure 28.15 : Supposed MIME types.
After you have verified the plug-in's resource information, open an AVI file from within the Navigator. You can also use wave or midi. The first file open loads your plug-in. Figure 28.16 shows how to play a video that comes with Windows 95. Now that you've loaded the plug-in one time, exit the Navigator with File|Exit.
Figure 28.16 : Playing the video.
After exit, the debugger should be aware of your plug-in module. As in Figure 28.17, you should see the plug-in's source files listed in the Modules window. Double-click on one of them to see the source.
Figure 28.17 : Finding the modules.
Now you can set a breakpoint. In Figure 28.18, a breakpoint is set in the NPP_StreamAsFile API.
Figure 28.18 : Setting a breakpoint.
After breakpoints are set, restart the Navigator and Go again with the debugger's main menu items: Run|Restart and Run|Go.
If all went well, you should hit the breakpoint on this run. In Figure 28.19, the AVI filename is checked after hitting the breakpoint.
Figure 28.19 : Hitting the breakpoint.
Here are the most important things to remember when porting to the Watcom compiler:
Remember that Watcom ships with MFC. Try to port one of the MFC examples in this book to Watcom.
The appendices are next, which include a listing of Netscape's product line, a listing of many of the currently available plug-ins, and a glossary of terms. Many of the plug-ins listed in Appendix B are included on the CD-ROM.