Message_messenger bug in Unicode environments

I encountered trouble trying to compile my applictaion using the class Message_Messenger:

the method

Standard_Boolean Message_Messenger:AddPrinter(const Handle(Message_Printer)& thePrinter)

generates an unresolved symbol linker error. The reason is a define in the standard library Winspool.h

#ifdef UNICODE
#define AddPrinter AddPrinterW
#else
#define AddPrinter AddPrinterA
#endif // !UNICODE

This preprocessor directive is supposed to select the correct (Unicode or non-Unicode) version of the windows function AddPrinter depending on the projects settings.

My workaround is to undefine 'Addprinter' in 'Message_Messenger.hxx' prior to the class declaration and redefine it afterwards in order to not break programms using the windows function.

The call to a Message_messenger-objects Addprinter function has to be handled as well, for example like this:

filePrinter = new Message_PrinterOStream("c:\\test\\OCC-Logfile.log", Standard_False, Message_Fail);
Handle(Message_Messenger) msgr = Message::DefaultMessenger();

//UGLY HACK: React to function name substitution for unicode from winspool.h since a function called "addprinter" is used in OCCT as well
#ifdef UNICODE
#undef AddPrinter
#endif
msgr->AddPrinter(filePrinter);
#ifdef UNICODE
#define AddPrinter AddPrinterW
#else
#define AddPrinter AddPrinterA
#endif // !UNICODE

sergey zaritchny's picture

Hi Tilman,
Thanks for your contribution.
Could you provide some additional information (necessary for certification procedure):
1. OS (Windows-Vista, Windows 7,..)
2. Compiler
3. Example of code which generated unresolved symbol linker error.
Regards

Tilman Leune's picture

Here are the requested additonal Details:

OS: Windows XP SP3
Compiler: MSVS 2008 Standard Edition

Example Code:

In a project set to use Unicode Strings, I used this snippet found in this forum:

Handle(Message_PrinterOStream) filePrinter;
filePrinter = new Message_PrinterOStream("c:\\test\\OCC-Logfile.log", Standard_False, Message_Fail);
Handle(Message_Messenger) msgr = Message::DefaultMessenger();
msgr->AddPrinter(filePrinter);

The linker raises this error (translated to english by me since i use a non-english version of VS)

5>OCCWrapper.obj : error LNK2019: Unresolved reference to external Symbol ""public: unsigned int __thiscall Message_Messenger::AddPrinterW(class Handle_Message_Printer const &)" (?AddPrinterW@Message_Messenger@@QAEIABVHandle_Message_Printer@@@Z)" in Funktion ""bool __cdecl ExportToFile(int,wchar_t *,enum TXDEFiletype)" (?ExportToFile@@YA_NHPA_WW4TXDEFiletype@@@Z)".
5>x:\release\winstart\bin\OCCWrapper.dll : fatal error LNK1120: 1 unresolved external reference

sergey zaritchny's picture

So,
I checked the provided example as on Standard Edition as on Express Edition of MSVS 2008 (SP1) with "Use Unicode Character Set" option (Win32 platform).
The specified problem (Unresolved reference...) was not reproduced (see below):
...
>Linking...
> Creating library W:\Projects\Test\TestUnicode\Debug\TKTest.lib and object W:\Projects\Test\TestUnicode\Debug\TKTest.exp
>Embedding manifest...
>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
>Copyright (C) Microsoft Corporation. All rights reserved.
>...
>Test - 0 error(s), 0 warning(s)
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

Regards

Tilman Leune's picture

Did you do a full rebuild of the OCCT-library?
In that case, the library function in TKernel will be mangled by the preprocessor directive as well, resulting in matched external references, as Message_Messenger.AddPrinter will be preprocessed to Messgage_Messenger.AddPrinterW in both header file and source file.

This should be verifiable: If you try a direct GetProcadress(TKERNELDLLHANDLE, "AddPrinter") using your newly built TKernel.dll, you should get a NULL-pointer returned, and a call to GetProcadress(TKERNELDLLHANDLE, "AddPrinterW") should yield a valid function pointer.

sergey zaritchny's picture

Ok, I understood.
At the moment OCCT itself provides only partial support of Unicode.
Put your attention, please on TCollection_ExtendedString class and corresponding methods: ConvertToUnicode() and so on...
So, to work with Unicode it is not necessary to rebuild OCCT with "Unicode character set" option.
Just use corresponding API to organize interface between your application and OCCT. At the same time I would like to inform you that we are working in this direction and I do hope to remove this limitation in the future.
Regards

Tilman Leune's picture

Thank you for the assistance.

Roman Lygin's picture

As far as I understand, the issue is not about the Unicode support but about the name collision. When you include windows.h first and then Message_Messenger.hxx, due to macros definition you either get AddPrinterA() or AddPrinterW() method declared in Message_Messenger. Obviously none exists, so you get a linker error. I recall similar clashes with other places, e.g. in Message_ProgressScale.cxx where ZERO and INFINITE constants are used. They are also defined in windows.h and may cause a problem.

So, to work-around this issue you need to ensure that you include Message_Messenger prior to windows.h.

Hope this helps.
Roman