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:
Here's the build tools dialog (showing the tools currently defined):
Here's the Edit Tool dialog for the PreProcessor tool:
And finally, the project manager local menu showing the new tool (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 https://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:
After the WSDL is parsed, you can see the imported structures and preview the generated code on the second page of the wizard.
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 : https://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 - "https://www.w3.org/2001/XMLSchema"
class USPSAddress;
// ************************************************************************ //
// Namespace : https://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 : https://webservices.eraserver.net/
// soapAction: https://webservices.eraserver.net/%operationName%
// transport : https://schemas.xmlsoap.org/soap/http
// style : document
// binding : ZipCodeResolverSoap
// service : ZipCodeResolver
// port : ZipCodeResolverSoap
// URL : https://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 : https://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= "https://webservices.eraserver.net/zipcoderesolver/zipcoderesolver.asmx?WSDL";
static const char* defURL = "https://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"https://webservices.eraserver.net/", L"utf-8");
InvRegistry()->RegisterDefaultSOAPAction(__interfaceTypeinfo(ZipCodeResolverSoap), L"https://webservices.eraserver.net/%operationName%");
InvRegistry()->RegisterInvokeOptions(__interfaceTypeinfo(ZipCodeResolverSoap), ioDocument);
/* USPSAddress */
RemClassRegistry()->RegisterXSClass(__classid(USPSAddress), L"https://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.
Connect with Us