Preview of C++ Builder 6

By: John Kaster

Abstract: John K briefly covers some of the new features in C++ Builder 6, complete with screen shots and sample code

Our C++ customers have eagerly awaited news of the latest release of C++ Builder 6. In this article, we'll take a quick look at some of the new features you will find in this release. There are many more new features and bug fixes in the product, but those will have to wait for other articles.

C++ Builder 6 goals

The goals for C++ Builder 6 are:

  • Increase the speed of C++ development.
  • Improve Project Management in the IDE.
  • Start down the cross-platform path with easy migration to our forthcoming C++ product for Linux.
  • Increase compliance with the ANSI C++ standard.
  • Provide e-business and internet development, with rapid web server and web services development.

Let's talk about some of these goals in this quick preview.

Speed of development

There are many new features coming into the IDE in this version that should make C++ development faster than ever. Many of the new technologies introduced in Delphi 6 will be available in C++ Builder 6. However, rather than provide screen shots on these new features that look similar to their Delphi counterparts, I'd like to talk about bug fixes, which is something our C++ Builder customers have been asking about for a while.

The IDE will not automatically change any directories or paths that your enter on Project|Options|Directories/Conditionals. For the longest time, the IDE has tried to outsmart the user and convert absolute paths to relative paths when it thought it made sense to do so. Starting with 6.0, the IDE will leave these settings exactly as the user enters them. This has been the top complaint Chris Hesik has heard from users over the last few years. I'm sure you'll be happy to know that's been fixed.

Another "fix" is being able to use environment variables as part of the paths specified on this dialog. Our C++ customers have been asking for that ability for a while, too.

There have been other IDE stability and usability bugs addressed that should be very welcome to our C++ Builder users. These should be published on our developer support pages soon.

Project Management

The project manager has received a lot of attention in this release of C++ Builder. This includes the ability to define custom build tools. Build tools fully participate in the build process, supporting:

  • Dependency checking
  • Compiler progress dialog
  • Stopping the build on an error
  • Full error reporting in the compiler message view

Build Tools

With a build tool, you can specify:

  • a list of supported file types, as well as the file types for which it is the default
  • the file type produced by running the tool
  • the command line to execute for the tool, which can include any number of predefined macros
  • a filter that is used to parse the output from the tool

A build tool will be invoked automatically for any file type for which it is the default tool. You can also manually invoke a build tool for any supported file type by right clicking on a supported file in the project manager. The tool will appear on the context menu. The build tool default filter fills the message view with anything written by the tool to stdout and stderr. You can write custom filters using the Open ToolsAPI. Custom filters receive the following information:

  • the name of the file being processed
  • the error code returned by the tool
  • StringLists representing stdout and stderr

GUI Glimpse

Here's the menu item for accessing the build tools:

Build Tools menu item

Here's the build tools dialog (showing the tools currently defined):

Build Tools dialog

Here's the Edit Tool dialog for the PreProcessor tool:

Edit Tool

And finally, the project manager local menu showing the new tool (PreProcess):

PreProcess

There will be additional work done on the Project Manager, such as providing more control over the build order, as well.

STL Support

The default STL implementation in C++ Builder 6 is STLPort. If you still want to use the Rogue Wave STL, you can add a project-level define (under Project|Options|Directories/Conditionals|Conditional Defines). By default (without this define) you get the STLPort implementation. By using the STLPort version of the STL, Borland has increased our ANSI C++ conformance.

Web Services

One of the new features you will see in C++ Builder 6 that extends what shipped with Kylix 2 and Delphi 6 is support for web services. C++ Builder 6 increases our interoperability with other SOAP development solutions, like .NET, Apache, SOAPLite, and so on. For a list of a variety of web services using various SOAP development solutions, go to www.xmethods.net. Current testing of our interoperability indicates that we can successfully connect to about 95% of the web services listed on XMethods. You can find more information on our Web Services Interoperability for our native-code products in the article Interoperability with Delphi's SOAP implementation.

Perhaps the most popular request we've had in the web services area is for a high level of interoperability with .NET web services. I'll use one of those as an example. XMethods lists a zip code resolver web service written in .NET. The WSDL file is found at http://webservices.eraserver.net/zipcoderesolver/zipcoderesolver.asmx?WSDL.

We can get the C++ language binding for this WSDL by running the WSDLImporter for C++ Builder 6 and providing the WSDL link to it. We can bring up the importer by selecting File|New|WebServices|WSDL Importer and put in the URI to the WSDL:

WSDL Import Loader

After the WSDL is parsed, you can see the imported structures and preview the generated code on the second page of the wizard.

WSDL Importer Preview

Clicking Finish generates the language binding code. The file is named automatically based on the URI. Here is the zipcoderesolver.h file.


// ************************************************************************ //
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL     : http://webservices.eraserver.net/zipcoderesolver/zipcoderesolver.asmx?WSDL
// Encoding : utf-8
// Version  : 1.0
// (2/7/2002 11:58:20 AM - $Revision:   1.0.1.0.1.76  $)
// ************************************************************************ //

#ifndef   zipcoderesolverH
#define   zipcoderesolverH

#include <System.hpp>
#include <InvokeRegistry.hpp>
#include <XSBuiltIns.hpp>
#include <SoapHTTPClient.hpp>


namespace NS_zipcoderesolver {

// ************************************************************************ //
// The following types, referred to in the WSDL document are not being represented
// in this file. They are either aliases[@] of other types represented or were referred
// to but never[!] declared in the document. The types from the latter category
// typically map to predefined/known XML or Borland types; however, they could also 
// indicate incorrect WSDL documents that failed to declare or import a schema type.
// ************************************************************************ //
// !:string          - "http://www.w3.org/2001/XMLSchema"

class  USPSAddress;



// ************************************************************************ //
// Namespace : http://webservices.eraserver.net/
// ************************************************************************ //
class USPSAddress : public TRemotable {
private:
  AnsiString      FStreet;
  AnsiString      FCity;
  AnsiString      FState;
  AnsiString      FShortZIP;
  AnsiString      FFullZIP;
public:
__published:
  __property AnsiString     Street = { read=FStreet, write=FStreet };
  __property AnsiString       City = { read=FCity, write=FCity };
  __property AnsiString      State = { read=FState, write=FState };
  __property AnsiString   ShortZIP = { read=FShortZIP, write=FShortZIP };
  __property AnsiString    FullZIP = { read=FFullZIP, write=FFullZIP };
};



// ************************************************************************ //
// Namespace : http://webservices.eraserver.net/
// soapAction: http://webservices.eraserver.net/%operationName%
// transport : http://schemas.xmlsoap.org/soap/http
// style     : document
// binding   : ZipCodeResolverSoap
// service   : ZipCodeResolver
// port      : ZipCodeResolverSoap
// URL       : http://webservices.eraserver.net/zipcoderesolver/zipcoderesolver.asmx
// ************************************************************************ //
__interface INTERFACE_UUID("{898E8D34-F2DD-4EFA-D0E2-B08F95EEB0C2}") ZipCodeResolverSoap : public IInvokable
{
public:
  virtual AnsiString      FullZipCode(const AnsiString accessCode, const AnsiString address, const AnsiString city, const AnsiString state) = 0; 
  virtual AnsiString      ShortZipCode(const AnsiString accessCode, const AnsiString address, const AnsiString city, const AnsiString state) = 0; 
  virtual AnsiString      CorrectedAddressHtml(const AnsiString accessCode, const AnsiString address, const AnsiString city, const AnsiString state) = 0; 
  virtual USPSAddress*    CorrectedAddressXml(const AnsiString accessCode, const AnsiString address, const AnsiString city, const AnsiString state) = 0; 
  virtual AnsiString      VersionInfo() = 0; 
};
typedef DelphiInterface<ZipCodeResolverSoap> _di_ZipCodeResolverSoap;

_di_ZipCodeResolverSoap GetZipCodeResolverSoap(bool useWSDL=false, AnsiString addr="");



#endif // __zipcoderesolver_h__

};     // NS_zipcoderesolver

#if !defined(NO_IMPLICIT_NAMESPACE_USE)
using  namespace NS_zipcoderesolver;
#endif

And here is the zipcoderesolver.cpp file.


// ************************************************************************ //
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL     : http://webservices.eraserver.net/zipcoderesolver/zipcoderesolver.asmx?WSDL
// Encoding : utf-8
// Version  : 1.0
// (2/7/2002 11:58:20 AM - $Revision:   1.0.1.0.1.76  $)
// ************************************************************************ //

#include <vcl.h>
#pragma hdrstop

#if !defined(zipcoderesolverH)
#include "zipcoderesolver.h"
#endif



namespace NS_zipcoderesolver {

_di_ZipCodeResolverSoap GetZipCodeResolverSoap(bool useWSDL, AnsiString addr)
{
  static const char* defWSDL= "http://webservices.eraserver.net/zipcoderesolver/zipcoderesolver.asmx?WSDL";
  static const char* defURL = "http://webservices.eraserver.net/zipcoderesolver/zipcoderesolver.asmx";
  static const char* defSvc = "ZipCodeResolver";
  static const char* defPrt = "ZipCodeResolverSoap";
  if (addr=="")
    addr = useWSDL ? defWSDL : defURL;
  THTTPRIO* rio = new THTTPRIO(0);
  if (useWSDL) {
    rio->WSDLLocation = addr;
    rio->Service = defSvc;
    rio->Port = defPrt;
  } else {
    rio->URL = addr;
  }
  _di_ZipCodeResolverSoap service;
  rio->QueryInterface(service);
  if (!service)
    delete rio;
  return service;
}


// ************************************************************************ //
// This routine registers the interfaces and types used by invoke the SOAP
// Service.
// ************************************************************************ //
static void RegTypes()
{
  /* ZipCodeResolverSoap */
  InvRegistry()->RegisterInterface(__interfaceTypeinfo(ZipCodeResolverSoap), L"http://webservices.eraserver.net/", L"utf-8");
  InvRegistry()->RegisterDefaultSOAPAction(__interfaceTypeinfo(ZipCodeResolverSoap), L"http://webservices.eraserver.net/%operationName%");
  InvRegistry()->RegisterInvokeOptions(__interfaceTypeinfo(ZipCodeResolverSoap), ioDocument);
  /* USPSAddress */
  RemClassRegistry()->RegisterXSClass(__classid(USPSAddress), L"http://webservices.eraserver.net/", L"USPSAddress");
}
#pragma startup RegTypes 32

};     // NS_zipcoderesolver

But wait, there's more!

This is just a small sample of what is in C++ Builder 6. I hope you have found something of interest to you in this article. I'd like to thank Chris Hesik and Bruneau Babet, two of our C++ Builder R&D Engineers for their help with producing this article.


Server Response from: ETNASC03