views:

600

answers:

2

I have a range of Win32 VCL applications developed with C++Builder from BCB5 onwards, and want to port them to ECB2009 or whatever it's now called.

Some of my applications use the old TNT/TMS unicode components, so I have a good mix of AnsiStrings and WideStrings throughout the code. The new version introduces UnicodeString, and a bunch of #defines that change the way functions like c_str behave.

I want to modify my code in a way that is as backwards-compatible as possible, so that the same code base can still be compiled and run (in a non-unicode fashion) on BCB2007 if necessary.

Particular areas of concern are:

  • Passing strings to/from Win32 API functions
  • Interop with TXMLDocument
  • 'Raw' strings used for RS232 comms, etc.

Rather than knife-and-fork the changes, I'm looking for guidelines that I can apply to ease the migration, while keeping backwards compatibility wherever possible.

If no such guidelines already exist, maybe we can formulate some here?

+4  A: 

The biggest issue is compatibility for C++Builder 2009 and previous versions, the Unicode differences are some, but the project configuration files have changed as well. From the discussions I've been following on the CodeGear forums, there are not a whole lot of choices in the matter.

I think the first place to start, if you have not done so, is the C++Builder 2009 release notes.

The biggest thing seen has been the TCHAR mapping (to wchar or char); using the STL string varieties may be a help, since they shouldn't be very different between the two versions. The mapping existed in C++Builder 2007 as well (with the tchar header).

Kris Kumler
+2  A: 

For any code that does not need to be explicitally Ansi or explitically Unicode, you should consider using the System::String, System::Char, and System::PChar typedefs as much as possible. That will help ease a lot of migration, and they work in previous versions.

When passing a System::String to an API function, you have to take into account the new "TCHAR maps to" setting in the Project options. If you try to pass AnsiString::c_str() when "TCHAR maps to" is set to "wchar_t", or UnicodeString::c_str() when "TCHAR maps to" is set to "char", you will have to perform appropriate typecasts. If you have "TCHAR maps to" set to "wchar_t". Technically, UnicodeString::t_str() does the same thing as TCHAR does in the API, however t_str() can be very dangerous if you misuse it (when "TCHAR maps to" is set to "char", t_str() transforms the UnicodeString's internal data to Ansi).

For "raw" strings, you can use the new RawByteString type (though I do not recommend it), or TBytes instead (which is an array of bytes - recommended). You should not be using Ansi/Wide/UnicodeString for non-character data to begin with. Most people used AnsiString as makeshift data buffers in past versions. Do not do that anymore. This is particularly important because AnsiString is now codepage-aware, and thus your data might get converted to other codepages when you least expect it.

Remy Lebeau - TeamB