Converting string macros/constants to wide characters/Unicode
Asked Answered
C

1

7

I have a Unicode Win32 application that uses 3rd party libraries, some of which provide constants for their version information as #defined (narrow) strings. For instance, libpng has the following:

#define PNG_LIBPNG_VER_STRING "1.5.4"
#define PNG_HEADER_VERSION_STRING \
 " libpng version 1.5.4 - July 7, 2011\n"

I'm appending the various statically linked libraries version information to my About Box for easy version tracking, and it seemed like it would be simple to convert this constant into a wide string.

My first attempt was TEXT(PNG_HEADER_VERSION_STRING), but that fails as

#define __TEXT(quote) L##quote

.. and LPNGHEADER_VERSION_STRING doesn't exist of course.

So I tried several combinations of double wrapping macros, and all sorts of ## tricks to attempt to add the L prefix to a macro'ed constant, but wasn't able to. Am I missing something simple? How would you handle:

#define VERSIONSTR "Test V1.2.3"
const char* ver= VERSIONSTR;
const wchar* wver = _T(VERSIONSTR); // fails, should be L"Test V1.2.3"
#define VERSIONSTRW _T(VERSIONSTR);  // fails also

programmatically, without simply adding a duplicate L"Test V1.2.3" and having to keep it in sync with the 3rd party library.

I know I can just convert it at runtime if I'm building for Unicode, but I thought surely there was a quick way to re-define this constant.

---UPDATE---

I missed the plot by doing something really stupid with my include structure. Fixing that allowed the double define wrapper to function as it should. Stupid on my part.

Cycad answered 12/7, 2011 at 18:58 Comment(2)
What compiler are you using? #define VERSIONSTRW _T(VERSIONSTR) works for me in VC++ 2008.Selfcontent
VS2003. I know its old, but its currently required. Perhaps its just a bug in my compiler?Cycad
D
8

The trick is to use two macros. When a macro is expanded, the arguments are macro-expanded before being substituted into the replacement list. So WIDEN(VERSIONSTR) becomes WIDEN2("Test V1.2.3").

#define WIDEN(quote) WIDEN2(quote)
#define WIDEN2(quote) L##quote

#define VERSIONSTR "Test V1.2.3"
#define VERSIONSTRW WIDEN(VERSIONSTR)
Docilla answered 12/7, 2011 at 19:14 Comment(2)
I had tried that previously. VS fails with the same error as before they were single wrapped. wchar *str = WIDEN(VERSIONSTR) results in error C2065: 'LVERSIONSTR' : undeclared identifierCycad
See my update. The double macro trick works fine in VS2003 (and later I assume). My stupidity kept me from seeing the obvious.Cycad

© 2022 - 2024 — McMap. All rights reserved.