11

So getting into the new millenia I rewrote my c++ code with:

int main(int argc, wchar_t **argv)

If built with either Unicode or MBCS options then when the app is run with a commandline arg, either directly or by dbl-click the filenames passed to argv[] are unreadable = in some mixture of chinese fonts.

Thanks for the comments - I will try and summaris(z)e them here for the search engine.

  1. wmain(int argc,char **argv) can only be used for a commandline (subsystem:console) app

  2. int winMain(int argc, wchar_t **argv) works for a gui (subsystem:windows) but the gui replaces it with it's own entry point. In the case of Qt this doesn't work

    qtmaind.lib(qtmain_win.obj) : error LNK2019: unresolved external symbol _main referenced in function _WinMain@16

The solution seems to be use main(int arc,char **argv) or main(int argc,wchar_t**argv) but ignore the argv. Then call QApplication with argv or NULL - the argv is ignored as Qt internally calls GetCommandLine().
Then use app.arguments to return the parsed arguments.
These can then be converted back into wchar with Qt's string functions if needed.

 QApplication app(argc, (char**)argv);  or  QApplication app(argc,NULL);  
 QStringList args = app.arguments();

Sorry I didn't originally flag this Qt because I didn't think that was relevant.
If somebody wants to edit this to also include how to do this in MFC - please do.

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
  • (I know the question is old but) you should post a self-answer instead of including the "summary" in the question. Questions are questions. – user202729 May 25 '18 at 05:49

3 Answers3

21

You need to name your entry point wmain: http://msdn.microsoft.com/en-us/library/fzc2cy7w(VS.80).aspx

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • It seems wmain can only be used in commandline app, wWinMain is for GUIs but clashes with the Qt library. – Martin Beckett Nov 04 '10 at 22:34
  • @Martin, I thought `main` could only be used for command line programs too, so I didn't consider this an issue. – Mark Ransom Nov 04 '10 at 22:43
  • Unfortunately you get the file name sent as a commandline arg when you dbl-click, I suppose it's really a Qt bug. – Martin Beckett Nov 04 '10 at 22:54
  • 4
    `wmain` is OK regardless of subsystem (GUI or console). However, MS linker is not smart about it, so with unconventional startup function you have to use linker `/entry` option to specify the entry point that calls that startup function. IIRC in this case it would be `/entry:wmainCRTStartup`. An alternative is to use the `GetCommandLine` API function and its near cousin that splits a command line into arguments (I forget the name, but it's interesting in that it's only available in Unicode version). That's probably what `wmainCRTStartup` does. Cheers & hth., – Cheers and hth. - Alf Nov 04 '10 at 22:55
  • @Alf - thats rubbish. Using /entry forces the application to bypass c-runtime initialization: statically scoped objects will not be constructed and other c++ runtime data structures will not be properly initialized. Never use /ENTRY unless you have specifically developed the app to only use safe C-library calls and that c++ programs will be broken. – Chris Becke Nov 05 '10 at 09:24
  • @Chris: you can see what's going on in the Visual Studio debugger. Including the source code. Hopefully seeing for yourself will convince you? Needless to say, your information, wherever you got it, is incorrect. Perhaps it's your own incorrect generalization of something you read? Cheers & hth. – Cheers and hth. - Alf Nov 05 '10 at 09:39
  • @Chris: perhaps the point you didn't get is that `wmainCRTStartup` (assuming I remembered the name correctly) is one of the four entry point functions provided by Microsoft's runtime library? – Cheers and hth. - Alf Nov 05 '10 at 09:56
  • Ah, true that. In which case the initialization is being done. so it is safe. It still shouldn't be necessary - the project switches choose an entry point that corresponds to the project type: dlls get a DllMiain, Exes get wMain, main, WinMain or wWinMain depending on the projects unicode and subsystem:windows or console switches. – Chris Becke Nov 05 '10 at 10:13
  • 2
    @Chris: I agree that it shouldn't be necessary to choose the entry point. The GNU toolchain deduces it automatically. Microsoft's linker doesn't, so Visual C++ is effectively non-conforming (not accepting standard `main` unless you add those little-known options) for GUI subsystem application. That said, the `main` signature is a Unix-dependency in the language. The C++ standard suggests UTF-8 encoding of the `main` args, but e.g. Win XP [cmd.exe] does not handle UTF-8 encoding: most commands just *silently fail* after a `chcp 65001`... :-( Cheers, – Cheers and hth. - Alf Nov 05 '10 at 10:27
  • thanks mark - not really the 'correct' answer, but it got a lot of useful discussion. – Martin Beckett Nov 05 '10 at 16:11
5

Try this:

#include <tchar.h>

int _tmain( int argc, TCHAR **argv )
{
  return 0;
}

_tmain is defined as wmain when compiled with the UNICODE option and as main when compiled with the MBCS option.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • 3
    Uh, don't use the MS `T` stuff unless you need to support Windows 9x while linking MFC dynamically (and don't want to rebuild MFC). With no MFC in the picture, and desire to support Windows 9x for Unicode program, just use Microsoft Layer for Unicode. Anyway, using `T` stuff is not just anachronism, it's recipe for trouble. :-) – Cheers and hth. - Alf Nov 04 '10 at 22:58
  • 1
    @Alf, curious to know how the `T` stuff can get you in trouble. Seems like the C++ rigid type system would warn you of any impending disaster. – Mark Ransom Nov 05 '10 at 02:22
  • 3
    @Mark: with the `T` stuff e.g. literals change from narrow to wide depending on whether certain macro symbols are defined when you compile. Typically the code is only tested with one set of macro definitions, e.g. building as Unicode. Building as ANSI (and the possibility of that was the whole point of the `T` stuff) then fails. Even if it doesn't fail it's more testing work (about twice as much, testing two different versions), and it's more work to write the code. That can also get you in trouble... :-) Cheers & hth., – Cheers and hth. - Alf Nov 05 '10 at 09:45
  • 1
    @Alf: Talk about fallacious reasoning! So according to you, if the requirements of a particular project necessitate both wide character and ASCII versions it's better to duplicate the project or use your own preprocessor switches all over rather than 2 build configuration that define and undefine the UNICODE symbol and use MS' TCHAR switches? continued ... – Praetorian Nov 05 '10 at 13:27
  • 1
    And if you don't care about one of the character sets, how does TCHAR hurt you? You're still going to test the case you care about and make sure it works. Also, using the "T stuff" function names feels a lot more natural than not, `LoadLibrary()` vs `LoadLibraryA()` for example. – Praetorian Nov 05 '10 at 13:28
  • @Praetorian: the opinion you attribute to me has not been expressed by me. Can't help with that (as you write you're employing fallacious reasoning), sorry. However, I can help with the problem you mention at the end, having to write `LoadLibraryA`. The simple solution to that, assuming that you don't also need to build the program as a Unicode version, is to *not* define the macro `UNICODE` (you may have to adjust your project settings). Cheers & hth., – Cheers and hth. - Alf Nov 05 '10 at 13:43
  • @Praetorian: oh, I can also help you if you *actually* need a Windows 9x version of your program. For that, read my *first* comment. Cheers, – Cheers and hth. - Alf Nov 05 '10 at 13:46
  • @Alf: OK, let's assume that I am trying to put words in your mouth. So, in your own words, how would you write the `main()` function posted above if you had to maintain both wide char and ASCII versions of your project? Also, if you write `LoadLibrary()` and undefine `UNICODE` instead of using `LoadLibraryA()` calls in your code you are using the very same "T stuff" scheme that you advise against using. AFAIK, all of MS' `TCHAR` switches are preprocessor and simply swap the `FunctioNameA()` and the `FunctionNameW()` versions based on preprocessor symbols. – Praetorian Nov 05 '10 at 14:48
  • @Pratorian: re the hypothetical case, I would get out of the project and firm as soon as possible. :-) Re `UNICODE` as being `T` stuff: no, there are two different sets of macros. `UNICODE` controls the `` macros, like `LoadLibrary`, while `_UNICODE` (IIRC) and `_MBCS`, or whatever it was, controls the `T` stuff, which is about things such as `tmain` and `T`-versions of standard library functions. These sets of macros do interact, through some sanity checks sprinkled throughout Microsoft's headers, but that doesn't affect anything in a program written for Unicode Windows. Cheers, – Cheers and hth. - Alf Nov 05 '10 at 16:22
  • The `TCHAR` names may be more natural for Windows API functions (`LoadLibrary`), but they're *less* natural for CRT functions (`_tcscmp` vs. `strcmp`). – dan04 Nov 05 '10 at 16:24
  • See also http://stackoverflow.com/questions/234365/is-tchar-still-relevant/3002494 – dan04 Nov 05 '10 at 16:33
5

You can use GetCommandLine function for that purpose.

Nemanja Trifunovic
  • 24,346
  • 3
  • 50
  • 88